• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > BufferedInputStream(缓冲输入流)详解_动力节点Java学院整理

BufferedInputStream(缓冲输入流)详解_动力节点Java学院整理

作者:skywang12345 字体:[增加 减小] 来源:互联网 时间:2017-05-28

skywang12345 通过本文主要向大家介绍了bufferedinputstream,螺栓球节点网架的详解,钢结构节点详解,nuke节点详解,框架扁梁节点构造详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

BufferedInputStream 介绍

BufferedInputStream 是缓冲输入流。它继承于FilterInputStream。
BufferedInputStream 的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持“mark()标记”和“reset()重置方法”。
BufferedInputStream 本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当我们通过read()读取输入流的数据时,BufferedInputStream会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完之后,输入流会再次填充数据缓冲区;如此反复,直到我们读完输入流数据位置。

BufferedInputStream 函数列表

BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)

synchronized int   available()
void   close()
synchronized void   mark(int readlimit)
boolean   markSupported()
synchronized int   read()
synchronized int   read(byte[] buffer, int offset, int byteCount)
synchronized void   reset()
synchronized long   skip(long byteCount)

</div>

BufferedInputStream 源码分析(基于jdk1.7.40)

package java.io;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class BufferedInputStream extends FilterInputStream {

  // 默认的缓冲大小是8192字节
  // BufferedInputStream 会根据“缓冲区大小”来逐次的填充缓冲区;
  // 即,BufferedInputStream填充缓冲区,用户读取缓冲区,读完之后,BufferedInputStream会再次填充缓冲区。如此循环,直到读完数据...
  private static int defaultBufferSize = 8192;

  // 缓冲数组
  protected volatile byte buf[];

  // 缓存数组的原子更新器。
  // 该成员变量与buf数组的volatile关键字共同组成了buf数组的原子更新功能实现,
  // 即,在多线程中操作BufferedInputStream对象时,buf和bufUpdater都具有原子性(不同的线程访问到的数据都是相同的)
  private static final
    AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
    AtomicReferenceFieldUpdater.newUpdater
    (BufferedInputStream.class, byte[].class, "buf");

  // 当前缓冲区的有效字节数。
  // 注意,这里是指缓冲区的有效字节数,而不是输入流中的有效字节数。
  protected int count;

  // 当前缓冲区的位置索引
  // 注意,这里是指缓冲区的位置索引,而不是输入流中的位置索引。
  protected int pos;

  // 当前缓冲区的标记位置
  // markpos和reset()配合使用才有意义。操作步骤:
  // (01) 通过mark() 函数,保存pos的值到markpos中。
  // (02) 通过reset() 函数,会将pos的值重置为markpos。接着通过read()读取数据时,就会从mark()保存的位置开始读取。
  protected int markpos = -1;

  // marklimit是标记的最大值。
  // 关于marklimit的原理,我们在后面的fill()函数分析中会详细说明。这对理解BufferedInputStream相当重要。
  protected int marklimit;

  // 获取输入流
  private InputStream getInIfOpen() throws IOException {
    InputStream input = in;
    if (input == null)
      throw new IOException("Stream closed");
    return input;
  }

  // 获取缓冲
  private byte[] getBufIfOpen() throws IOException {
    byte[] buffer = buf;
    if (buffer == null)
      throw new IOException("Stream closed");
    return buffer;
  }

  // 构造函数:新建一个缓冲区大小为8192的BufferedInputStream
  public BufferedInputStream(InputStream in) {
    this(in, defaultBufferSize);
  }

  // 构造函数:新建指定缓冲区大小的BufferedInputStream
  public BufferedInputStream(InputStream in, int size) {
    super(in);
    if (size <= 0) {
      throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
  }

  // 从“输入流”中读取数据,并填充到缓冲区中。
  // 后面会对该函数进行详细说明!
  private void fill() throws IOException {
    byte[] buffer = getBufIfOpen();
    if (markpos < 0)
      pos = 0;      /* no mark: throw away the buffer */
    else if (pos >= buffer.length) /* no room left in buffer */
      if (markpos > 0) { /* can throw away early part of the buffer */
        int sz = pos - markpos;
        System.arraycopy(buffer, markpos, buffer, 0, sz);
        pos = sz;
        markpos = 0;
      } else if (buffer.length >= marklimit) {
        markpos = -1;  /* buffer got too big, invalidate mark */
        pos = 0;    /* drop buffer contents */
      } else {      /* grow buffer */
        int nsz = pos * 2;
        if (nsz > marklimit)
          nsz = marklimit;
        byte nbuf[] = new byte[nsz];
        System.arraycopy(buffer, 0, nbuf, 0, pos);
        if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
          throw new IOException("Stream closed");
        }
        buffer = nbuf;
      }
    count = pos;
    int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
    if (n > 0)
      count = n + pos;
  }

  // 读取下一个字节
  public synchronized int read() throws IOException {
    // 若已经读完缓冲区中的数据,则调用fill()从输入流读取下一部分数据来填充缓冲区
    if (pos >= count) {
      fill();
      if (pos >= count)
        return -1;
    }
    // 从缓冲区中读取指定的字节
    return getBufIfOpen()[pos++] & 0xff;
  }

  // 将缓冲区中的数据写入到字节数组b中。off是字节数组b的起始位置,len是写入长度
  private int read1(byte[] b, int off, int len) throws IOException {
    int avail = count - pos;
    if (avail <= 0) {
      // 加速机制。
      // 如果读取的长度大于缓冲区的长度 并且没有markpos,
      // 则直接从原始输入流中进行读取,从而避免无谓的COPY(从原始输入流至缓冲区,读取缓冲区全部数据,清空缓冲区, 
      // 重新填入原始输入流数据)
      if (len >= getBufIfOpen().length && markpos < 0) {
        return getInIfOpen().read(b, off, len);
      }
      // 若已经读完缓冲区中的数据,则调用fill()从输入流读取下一部分数据来填充缓冲区
      fill();
      avail = count - pos;
      if (avail <= 0) return -1;
    }
    int cnt = (avail < len) ? avail : len;
    System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
    pos += cnt;
    return cnt;
  }

  // 将缓冲区中的数据写入到字节数组b中。off是字节数组b的起始位置,len是写入长度
  public synchronized int read(byte b[], int off, int len)
    throws IOException
  {
    getBufIfOpen(); // Check for closed stream
    if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
      throw new IndexOutOfBoundsException();
    } else if (len == 0) {
      return 0;
    }

    // 读取到指定长度的数据才返回
    int n = 0;
    for (;;) {
      int nread = read1(b, off + n, len - n);
      if (nread <= 0)
        return (n == 0) ? nread : n;
      n += nread;
      if (n >= len)
        return n;
      // if not closed but no bytes available, return
      InputStream input = in;
      if (input != null && input.available() <= 0)
        return n;
    }
  }

  // 忽略n个字节
  public synchronized long skip(long n) throws IOException {
    getBufIfOpen(); // Check for closed stream
    if (n <= 0) {
      return 0;
    }
    long avail = count - pos;

    if (avail <= 0) {
      // If no mark position set then don't keep in buffer
      if (markpos <0)
        return getInIfOpen().skip(n);

      // Fill in buffer to save bytes for reset
      fill();
      avail = count - pos;
      if (avail <= 0)
        return 0;
    }

    long skipped = (avail < n) ? avail : n;
    pos += skipped;
    return skipped;
  }

  // 下一个字节是否存可读
  public synchronized int available() throws IOException {
    int n = count - pos;
    int avail = getInIfOpen().available();
    return n > (Integer.MAX_VALUE - avail)
          ? Integer.MAX_VALUE
          : n + avail;
  }

  // 标记“缓冲区”中当前位置。
  // readlimit是marklimit,关于marklimit的作用,参考后面的说明。
  public synchronized void mark(int readlimit) {
    marklimit = readlimit;
    markpos = pos;
  }

  // 将“缓冲区”中当前位置重置到mark()所标记的位置
  public synchronized 



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • BufferedInputStream(缓冲输入流)详解_动力节点Java学院整理
  • ByteArrayInputStream简介和使用_动力节点Java学院整理
  • BufferedInputStream(缓冲输入流)详解_动力节点Java学院整理
  • ByteArrayInputStream简介和使用_动力节点Java学院整理

相关文章

  • 2017-05-28Spring Boot(五)之跨域、自定义查询及分页
  • 2017-05-28ObjectInputStream 和 ObjectOutputStream 介绍_动力节点Java学院整理
  • 2017-05-28Map获取键值,Map的几种遍历方法总结(推荐)
  • 2017-05-28SWT(JFace)小制作 FileBrowser文件浏览
  • 2017-05-28Java Annotation详解及实例代码
  • 2017-05-28SpringBoot下的值注入(推荐)
  • 2017-05-28java 中JXL操作Excel实例详解
  • 2017-05-28深入理解java异常处理机制的原理和开发应用
  • 2017-05-28SWT(JFace)体验之Sash(活动控件)
  • 2017-05-28Java语言实现简单FTP软件 FTP软件效果图预览之下载功能(2)

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • SpringBoot中自定义注解实现控制器访问次数限制实例
    • Java追加文件内容的三种方法实例代码
    • 实例解析JAVA中代码的加载顺序
    • Java中Properties类的操作实例详解
    • 浅谈spring和spring MVC的区别与关系
    • HashMap和Hashtable的详细比较
    • 详解Java回调的原理与实现
    • Java vector的详解及实例
    • SpringMVC解析JSON请求数据问题解析
    • Spring Session实现分布式session的简单示例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有