当前位置: 代码迷 >> 综合 >> Java IO (7) -- BufferedInputStream 类 BufferedOutputStream 类
  详细解决方案

Java IO (7) -- BufferedInputStream 类 BufferedOutputStream 类

热度:4   发布时间:2023-12-16 13:26:46.0

文章目录

    • 1. 概念
    • 2. 字段
      • 1. BufferedInputStream
      • 2. BufferedOutputStream
    • 3. 方法
      • 1. 构造器
        • 1. BufferedInputStream
        • 2. BufferedOutputStream
      • 2. 其他方法
        • 1. BufferedInputStream
        • 2. BufferedOutputStream
    • 4. 案例
    • 5. 扩展

1. 概念

BufferedInputStream和BufferedOutputStream都是缓冲流,缓冲流实际上里面有一个缓冲区,即字节数组,用流读取存储在硬盘上较大文件的时,频繁从硬盘中读取数据效率比较低,花费时间较长.缓冲流的作用就是将数据先读取到内存里面,然后从内存里面读取数据,读取速度得到很大的提升

2. 字段

1. BufferedInputStream

  1. protected volatile byte buf[]:缓冲输入流中的缓冲区
  2. protected int count:缓冲输入流里面的有效字节数
  3. protected int pos:从缓冲区读取字节数据的当前位置
  4. protected int markpos = -1:缓冲区标记的位置,当调用mark()方法的时候,会将缓冲区当前位置pos保存到markpos
  5. protected int marklimit:mark()方法标记后再调用reset()方法之前最多读取的字节
  6. private static int DEFAULT_BUFFER_SIZE = 8192;

2. BufferedOutputStream

  1. protected byte buf[]:冲输出流中缓冲区
  2. protected int count:缓冲输出流中有效的字节数

3. 方法

1. 构造器

1. BufferedInputStream

  1. public BufferedInputStream(InputStream in) {this(in, DEFAULT_BUFFER_SIZE);}:创建的默认大小8192字节的字节数组
  2. public BufferedInputStream(InputStream in, int size):建的是指定size大小字节数组的缓冲输入流

2. BufferedOutputStream

  1. public BufferedOutputStream(OutputStream out) { this(out, 8192);}:创建默认大小为8192字节的缓冲输出流
  2. public BufferedOutputStream(OutputStream out, int size):创建指定大小size的缓冲输出流

2. 其他方法

1. BufferedInputStream

  1. public synchronized int read() throws IOException:从缓冲区读取一个字节
  2. public synchronized int read(byte b[], int off, int len) throws IOException:将缓冲区的数据读取到字节数组b的off位置开始,长度为len
  3. public synchronized long skip(long n) throws IOException:跳过字节的数
  4. public synchronized int available() throws IOException:从输入流中可读取字节总数的估算值
  5. public synchronized void mark(int readlimit):对缓冲区当前位置 pos 进行标记.并设置标记后可读取的最大值readlimit
  6. public synchronized void reset() throws IOException:将缓冲区的位置重置到 mark 标记的位置
  7. public boolean markSupported():是否支持标记
  8. public void close() throws IOException:关闭输入流

2. BufferedOutputStream

  1. public synchronized void write(int b) throws IOException:将数据b写到缓冲数组buf中
  2. public synchronized void write(byte b[], int off, int len) throws IOException:将字节数组b中off索引开始,长度为len个字节写到缓冲区中
  3. public synchronized void flush() throws IOException:刷新缓冲区,将缓冲区里面的数据写到输出流中

4. 案例

通过BufferedInputStream和BufferedOutputStream复制,效率极大提高

public class BufferedInputStreamDemo {
    public static void main(String[] args) throws IOException {
    File source = new File("D:\\软件.zip");File dest = new File("D:\\copy\\soft.zip");copyFile(source, dest);}private static void copyFile(File source, File dest) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));byte buffer[] = new byte[1024];int len = 0;while ((len = bis.read(buffer)) != -1) {
    bos.write(buffer);}bis.close();bos.close();}
}

5. 扩展

关于缓冲输入流填充方法fill().存在多种情况,分析如下:

  1. 缓冲区没有标记的情况下,即markpos<0时,缓冲区中已被读取过的字节不需要保存.即pos>=count时,会将pos和count重置为0.然后从输入流读取数据填充缓冲区0到buffer.length之间的位置
    在这里插入图片描述
  2. 缓冲区标记的情况下.
    1. 即markpos>=0情况下当markpos>0的时,下次刷新缓冲的时候,需要将markpos到pos之间数据保留.从输入流中读取数据填充pos到buffer.length之间的位置.如下图,当markpos>0时,并且pos>=buffer.length.下次读取输入流的里面数据的时候,会将markpos到pos之间的数据保存.
      在这里插入图片描述
    2. 当markpos=0的时候,buffer.length>marklimit,并且pos>buffer.length表示的是缓冲区里面没有剩余的位置.如果继续保留markpos到pos之间数据,那么刷新缓冲区之后,缓冲区依旧没有剩余位置,因为pos>=buffer.length.缓冲区没有空出位置,所以marklimit存在意义就是进行一个限定,根据buffer.length与marklimit大小来判断标记是否失效.源码中buffer.length>=marklimit的时候,标记失效.缓冲区里面0到buffer.length之间的位置是空的.可以进行填充
    3. 当markpos=0.buffer.length<marklimit,并且pos>buffer.length表示缓冲区没有剩余位置.则需要扩容;如下,扩充后容量的是2*pos和marklimit中的最小值.扩容后缓冲区会保留原先0-pos之间的数据.然后从输入流继续读取数据
      在这里插入图片描述
  相关解决方案