字节流在读取文件时每次读取一个字节都会去操作磁盘
这样如果数据量大的话,就会很频繁的操作磁盘。效率低下。
但如果使用了缓冲流,JAVA程序就会一次性从磁盘拉取大量数据先放到JAVA内存中。然后在优先从这个内存读取。如果读完了。在重新从磁盘在拉取大量数据。这样就大大的减少了操作磁盘的频率,从内存读取数据的效率要远高于从磁盘读取的效率。
字节缓冲流
1,字节流使用缓冲流读取数据和不使用缓冲流读取数据对比
(1)字节输入缓冲流BufferInputStream
InputStream下有一个BufferInputStream字节输入缓冲流,它用于实现字节输入流的高效读取。
实例文件目录如下,这是一个6.4M大小左右的文本文件
字节输入缓冲流创建步骤:
1,创建一个字节输入流比如FileInputStream并令其获取pro文件的File对象
2,创建一个字节输入缓冲流BufferInputStream并令其获取一个字节输入流比如FileInputStream
File file = new File("F:/java/pro.txt");
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
这样就创建完成,接下来就能读取数据了。读取方法和字节输入流一致。今天我们要对比两种读取方法的效率
//字节输入流
public static void inputStream() throws IOException {
File file = new File("F:/java/pro.txt");
InputStream inputStream = new FileInputStream(file);
long l = System.currentTimeMillis();
while (inputStream.read()!=-1){ }
long l1 = System.currentTimeMillis();
System.out.print(l1-l);
}
//字节输入缓存流
public static void bufferInputStream() throws IOException {
File file = new File("F:/java/pro.txt");
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
long l = System.currentTimeMillis();
//缓存流高效读取
while (bufferedInputStream.read()!=-1){ }
long l1 = System.currentTimeMillis();
System.out.print(l1-l);
//关流
}
分别执行上述两个方法,结果如下:
这是普通字节流
这是缓存流
可以看到极其明显的效率提升。。
(2)字节输出缓冲流BufferOutputStream
字节输出缓冲流是OutputStream底下的BufferOutputStream,创建过程是一样的。
1,先创建一个File对象指向一个路径,然后在创建一个字节输出流并令其获取这个File对象。
2,接着在创建一个字节缓冲输出流,并令其获取一个字节输出流
File file = new File("F:/java/pro.txt");
OutputStream outputStream = new FileOutputStream(file);
//创建缓冲输出流
OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
接下来同样对比缓存流和非缓存流的效率:
上图是文件目录,目的是把pro文本里的内容给写到pro1中。也就是复制。我们来看看缓冲流和非缓冲流的速度。
File file = new File("F:/java/pro.txt");
File file1 = new File("F:/java/pro1.txt");
InputStream inputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
OutputStream outputStream = new FileOutputStream(file1);
//缓冲输出流
OutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
int len = 0;
long l, l1,time = 0L;
while ((len=bufferedInputStream.read())!=-1){
l = System.currentTimeMillis();
//缓冲流
//bufferedOutputStream.write(len);
//非缓冲流
outputStream.write(len);
l1 = System.currentTimeMillis();
//这样就能只记录写的时间了
time+=(l1-l);
}
System.out.print(time);
//关流
分别放开缓冲流和非缓冲流的注释并执行得到以下结果:
非缓冲流
缓冲流
可以看到及其明细的效率提升
如果你没有关流或调用flush会发现pro1仍然成功写入了数据,缓冲流不是要调用flush()才会把数据写进去吗?
缓冲流默认的缓冲区大小是8K,也就是说你往这个缓冲区塞的数据超过8K那么它就会自动的刷新缓冲来重新放数据。所以上述使用字节输出缓冲流但没有关流或调用flush()的结果如下
所以如果发现没调用flush()或关流还是往里面写的数据,原因就是这样。所以实际上还是要调用flush()或关流的。这个别忘了。
字符缓冲流
1,字符输入缓冲流BurrferReader
创建方法:
(1)创建一个字符输入流并令其获取pro文本的File对象
(2)创建一个字符输入缓冲流BurrferReader并令其获取一个字符输入流
File file = new File("F:/java/pro.txt");
Reader reader = new FileReader(file);
//创建一个字符缓冲输入流
Reader buf = new BufferedReader(reader);
long l = System.currentTimeMillis();
//缓冲流
while (buf.read()!=-1){}
//非缓冲流
//while (reader.read()!=-1){ }
long l1 = System.currentTimeMillis();
System.out.print(l1-l);
分别放开缓冲流和非缓冲流的注释并执行,结果如下
缓冲流
非缓冲流
可以看到有一点效率差距的。
2,字符输出缓冲流BufferWriter
创建方法:
(1)创建一个字符输出流并令其获取pro1文本的File对象
(2)创建一个字符输出缓冲流BufferWriter并令其获取一个字符输出流
同样进行文本文件的复制操作来看看效果
把文本pro的内容写入到pro1中。大小8.7M左右
File file = new File("F:/java/pro.txt");
File file1 = new File("F:/java/pro1.txt");
Reader reader = new FileReader(file);
Reader buf = new BufferedReader(reader);
Writer writer = new FileWriter(file1);
//字符缓冲输出流
Writer bufW = new BufferedWriter(writer);
long l,l1,time=0L;int len;
while ((len =buf.read())!=-1){
l = System.currentTimeMillis();
//缓冲流高效写入
//bufW.write(len);
//非缓冲流写入
writer.write(len);
l1 = System.currentTimeMillis();
time+=(l1-l);
}
//关流
System.out.print(time);
分别放开缓冲流和非缓冲流的注释并执行,结果如下
缓冲流:
非缓冲流:
可以看到效率的差距.
问题:
1,字符流使用缓冲和非缓冲的速度差距并没有字节流的那么如此大。是否有必要使用缓冲流?
当然是有必要的。虽然没那么多。但还是提升很多的。
2,字符流自带的缓冲和缓冲流的缓冲有什么区别吗?
这个我没具体研究过。但是大致看了下源码。简单来说就是字符流的缓冲实现更复杂。导致速度慢。。。。。有哪个大佬能解释下就更好了