缓冲流
BufferedInputStream 缓冲输入流
前面的练习告诉我们使用缓冲数组读取的效率更高,为了方便的大家的操作,sun
位大家提供了一个缓冲输入字节流对象,让我们可以更高效率的读取文件。
输入字节流的体系
InputStream 输入字节流的基类
|——FileInputStream 读取文件的字节流
|——BufferedInputStream 缓冲输入字节流,主要为了提高读取文件数据的效率.其实该类非常的简单,只是维护了一个8kB的字节数组而已
注意:凡是缓冲流都不具备读写文件的能力
BufferedInputStream 的使用步骤
1、找到目标文件
2、建立数据的输入通道(FielinputStream)
1、建立数据的缓冲输入字符流
2、输入数据
3、关闭通道资源
问题一:为什么创建BufferedInputStream独享的时候,非要传入一个FileInputStream对象?
是这样的,上面注意里面说,缓冲流不具备读取文件的能力,如果要去读写一个文件的话,必须要给它传递一个InputStream或者OutputStream对象。也就是说,BufferedInputStream对象本身也没有和文件建立一个通道,顺气自然的可以回答下一个问题
问题二:缓冲流关闭资源的问题。
只需要一步,fileInputStream.close() 关闭文件即可,因为bufferedInputStream本身并未建立通道但是BufferedInputStream也有一个close方法,查看源码就可以知道,这个方法里面调用的还是InputStream的clos方法,所以,fileInputStream.close()和BufferedInputStream.close()只需调用一个即可
问题三:下面的演示可以看到bufferedInputStream对象和fileInputStream对象读取数据基本上是一样一样的,都是read呢么,缓冲流的效率到底是怎么提高的呢?
这个查看一下BufferedInputStream的源码可以看得很清楚,搞清这个问题,更容易看到问题的本质。看一下BufferedInputStream的read的源码,你会发现他是这样操作的:在一个适当的机会,直接从硬盘上独处8kB的数据,存储到bufferInputStream维护的buf数组中,当你取数据的时候,BufferedInputStream是直接从自己维护的8kb的内存中帮你取数据,而不是像FileInputStream那样你去一个数据它就帮你从硬盘上读一个数据,相比之下,一个从硬盘取数据,一个从内存去数据,孰快孰慢立见分晓。这才是真正的缓冲技术。
BufferedInputStream真的就只是在内部维护了一个buf而已,当然在在创建bufferedInputStream实现的时候也稍微的多了一步,多以通函情况下,还是自己使用FileInputStream然后自己维护一个buf就可以了。
1 public static void readTeset2() throws IOException 2 { 3 //找到目标文件 4 File file = new File("D:\b.txt"); 5 //建立数据输入通道 6 FileInputStream fileInputStream = new FileInputStream(file); 7 //建立缓冲输入字节流 8 BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 9 //读取文件数据 10 int content = 0; 11 while((content = bufferedInputStream.read())!=-1) 12 { 13 System.out.print((char)content); 14 } 15 //关闭资源 16 bufferedInputStream.close(); 17 }
输出字节流
OutputStream 所有输出字节流的基类
|——FIleOutputStream 向文件输出数据的输出字节流
|——BufferedOutputStream 缓冲输出字节流,就是为了提高输出的效率,内部维护了一个8k b的字节数组
BufferedOutputStream的使用步骤
1、找到目标文件
2、建立数据的输出通道 FIleOutputStream
3、建立缓冲输出字节流对象
4、输出数据,别忘了配合使用flush
BufferedOutputStream 注意细节
1、使用BufferedOutputStream写数据的时候,它的write方法实现吧数据写到它维护的内部数组中。
2、使用BufferedOutputStream写数据的时候,它的write方法实现吧数据写到它维护的内部数组中,如果需要把内部字节数组中的数据写到硬盘上,这是需要调用flush方法或者close方法,flush方法的作用,就是把数组中的数据写到硬盘上或者当内部维护的字节数组装满的时候也会自动调用flush把数组中的数据刷出到硬盘。
1 public static void main(String[] args) throws IOException 2 { 3 //找到目标文件 4 File file = new File("D:\a.txt"); 5 //建立输出字节流 6 FileOutputStream fileOutputStream = new FileOutputStream(file); 7 //建立缓冲输出字节流 8 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); 9 10 //把数据写出 11 bufferedOutputStream.write("hello world!".getBytes()); 12 bufferedOutputStream.flush(); 13 //关闭资源 14 bufferedOutputStream.close(); 15 } 16 //使用缓冲流拷贝图片 17 public static void copyImage()throws IOException 18 { 19 long start = System.currentTimeMillis(); 20 //找到目标文件 21 File inFile = new File("D:\1.jpg"); 22 File outFile = new File("E:\1.jpg"); 23 //建立输出输出流 24 FileInputStream fileInputStream = new FileInputStream(inFile); 25 FileOutputStream fileOutputStream = new FileOutputStream(outFile); 26 //建立缓冲输出输出流 27 BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 28 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); 29 //边读边写 30 int content = 0; 31 // int length = bufferedInputStream.read(buf);//如果传入了缓存数组,内容是存储到缓冲数组中,返回的是存储到缓存中的字节个数 32 while((content = bufferedInputStream.read())!=-1)//如果使用read方法没有传入缓冲数组,那么返值是读到的内容,返回的是对应的int值 33 { 34 bufferedOutputStream.write(content); 35 bufferedOutputStream.flush();//这里不需要刷新,为什么?因为这里每读一个字节就刷新一次,这样反而降低了效率,倒不如,让他自己写满之后自己刷出去 36 } 37 bufferedOutputStream.close(); 38 bufferedInputStream.close(); 39 long end = System.currentTimeMillis(); 40 41 System.out.println((end - start)); 42 }
小结 字节流:
输入字节流
InputStream 输入字节流的基类 抽象类
|——FileInputStream 读取文件的输入字节流
|——BufferedInputStream 缓冲输入字节流,缓冲输入字节流的目的,为了提高读取文件的效率,该类其实就是在内部维护了一个8kB的缓冲字节数组。
输出字节流
OutputStrea输出字节流的基类 抽象类
|——FileOutputStream 向文件输出数据的输出字节流
|——BufferedOutputStream 缓冲输出字节流该类出现的目的,是为了提高写数据的效率,其实该类内部也是维护了一个8kB的数组而已,当调用起write方法的时候,数据默认是向其内部的数组中存储的,只要调用flush方法货值是close或者是8kB的数组存储满数据之后,才会想硬盘输出。