JAVA-7 BufferedInputStream/BufferedOutputStream

其它类:

InputStream/OutputStream:https://blog.csdn.net/sinat_27180253/article/details/82185306

ObjectInputStream/ObjectOutputStream:https://blog.csdn.net/sinat_27180253/article/details/82185460

ByteArrayInputStream/ByteArrayOutputStream:https://blog.csdn.net/sinat_27180253/article/details/82185609

DataInputStream/DataOutputStream:https://blog.csdn.net/sinat_27180253/article/details/82186009

BufferedInputStream

1.类功能简介

缓冲字节输入流、作为FilterInputStream的一个子类、所提供的功能是为传入的底层字节输入流提供缓冲功能、通过底层字节输入流(in)中的字节读取到自己的buffer中(内置缓存字节数组)、然后程序调用BufferedInputStream的read方法将buffer中的字节读取到程序中、当buffer中的字节被读取完之后、BufferedInputStream会从in中读取下一个数据块到buffer中供程序读取、直到in中数据被读取完毕、这样做的好处一是提高了读取的效率、二是减少了打开存储介质的连接次数、详细的原因下面BufferedOutputStream有说到。其有个关键的方法fill()就是每当buffer中数据被读取完之后从in中将数据填充到buffer中、程序从内存中读取数据的速度是从磁盘中读取的十倍!这是一个很恐怖的效率的提升、同时我们也不能无禁止的指定BufferedInputStream的buffer大小、毕竟、一次性读取in中耗时较长、二是内存价格相对昂贵、我们能做的就是尽量在其中找到合理点。一般也不用我们费这个心、创建BufferedInputStream时使用buffer的默认大小就好。

构造方法

  • BufferedInputStream (InputStream in); //使用默认buf大小、底层字节输入流构建bis
  • BufferedInputStream (InputStream in, int size); //使用指定buf大小、底层字节输入流构建bis

一般方法

  • int available(); //返回底层流对应的源中有效可供读取的字节数
  • void close(); //关闭此流、释放与此流有关的所有资源
  • boolean markSupport(); //查看此流是否支持mark、此方法一直返回true
  • void mark(int readLimit); //标记当前buf中读取下一个字节的下标
  • int read(); //读取buf中下一个字节
  • int read(byte[] b, int off, int len); //读取buf中下一个字节
  • void reset(); //重置最后一次调用mark标记的buf中的位子
  • long skip(long n); //跳过n个字节、 不仅仅是buf中的有效字节、也包括in的源中的字节

 

BufferedOutputStream 

1.类功能简介

BufferedOutputStream:缓存字节输出流,作为FilterInputStream的一个子类,为传入的底层字节输出流提供缓存功能,同样当使用底层字节输出流向目的地中写入字节或者字节数组时,没写入一次就要打开一次到目的地的连接,这样频繁的访问不断效率底下,也有可能会对存储介质造成一定的破坏,比如当我们向磁盘中不断的写入字节时,夸张一点,将一个非常大单位是G的字节数据写入到磁盘的指定文件中的,没写入一个字节就要打开一次到这个磁盘的通道,这个结果无疑是恐怖的,而当我们使用BufferedOutputStream将底层字节输出流,比如FileInputStream包装一下之后,我们可以在程序中先将要写入到文件中的字节写入到BufferedOutputStream的内置缓存空间中,然后当达到一定数量时,一次性写入FileInputStream流中,此时FileInputStream就可以打开一次通道,将这个数据块写入到文件中,这样做虽然不可能达到一次访问就将所有数据写入磁盘中的效果,但也大大提高了效率和减少了磁盘的访问量!这就是其意义所在。

他的具体工作原理在这里简单提一下:当程序中每次将字节或者字节数组写入到BufferedOutputStream中时,都会检查BufferedOutputStream中的缓存字节数组buf(buf的大小是默认的或者在创建bos时指定的,一般使用默认的就好)是否存满,如果没有存满则将字节写入到buf中,如果存满,则调用底层的writer(byte[] b, int off, int len)将buf中的所有字节一次性写入到底层out中,如果写入的是字节数组,如果buf中已满则同上面满的时候的处理,如果能够存下写入的字节数组,则存入buf中,如果存不下,并且要写入buf的字节个数小于buf的长度,则将buf中所有字节写入到out中,然后将要写入的字节存放到buf中(从下标0开始存放),如果要写入out中的字节超过buf的长度,则直接写入out中。

构造方法

  • BufferedOutputStream(OutputStream out); //使用默认大小,底层字节输出流构造bos
  • BufferedOutputStream(OutputStream out, int size); //使用指定大小,底层字节输出流构造bos

一般方法

  • void flush(); //将写入bos中的数据flush到out指定的目的地中,注意这里不是flush到out中,因为其内部又调用了out.flush()
  • synchronized void close() //关闭
  • write(byte b); //将一个字节写入到buf中
  • write(byte[] b, int off, int len); //将b的一部分写入buf中

 

package com.stydy.stream;

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

public class BufferedStream {

     // 文件路径

     public static final String filePath = "D:" + File.separator + "ZZ" + File.separator + "stream.txt";

     //private static String msg = "大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好!!";

     private static String msg = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

     public static void main(String[] args) throws Exception {

          //testBufferedOutputStream();

          testBufferedInpuStream();

     }

     public static void testBufferedOutputStream() throws Exception {

          BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)));

          bos.write(msg.getBytes());

          //跳过第一个字节

          //bos.write(msg.getBytes(), 1, msg.getBytes().length-1);

          bos.flush();

     }

     public static void testBufferedInpuStream() throws Exception {

          BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(filePath)));

          for (int i = 0; i < 10; i++) {

              if (bis.available() >= 0) {

                   System.out.println(byteToString((byte) bis.read()));

              }

          }

          if (!bis.markSupported()) {

              return;

          }

          // 标记"当前索引位子" 即第11个字节 k

          bis.mark(6666);

          // 丢弃10个字节。

          bis.skip(10);

          // 读取剩下的b.length个字节

          byte[] b = new byte[1024];

          int n1 = bis.read(b, 0, b.length);

          System.out.println("剩余有效字节 : " + n1);

          printByteValue(b);

          

          // 重置输入流最后一次调用mark()标记的索引位置

          bis.reset();

          int n2 = bis.read(b, 0, b.length);

          System.out.println("剩余有效字节 : " + n2);

          printByteValue(b);

     }

     //输出字节

     private static void printByteValue(byte[] buf) {

          for (byte b : buf) {

              if (b != 0) {

                   System.out.print(byteToString(b) + " ");

              }

          }

     }

     //字节转字符

     private static String byteToString(byte b) {

          byte[] bAray = {b};

          return new String(bAray);

     }

}

总结

对于BufferedInputStream、BufferedOutputStream、本质就是为底层字节输入输出流添加缓冲功能、先将底层流中的要读取或者要写入的数据先以一次读取一组的形式来讲数据读取或者写入到buffer中、再对buffer进行操作、这样不但效率、还能节省资源。最后、在程序中、出于效率的考虑、也应为低级流使用这两个类进行装饰一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章