一:缓冲流简介:为什么能提升效率
● 原先没有缓冲流的情况:通过FileInputStream(文件输入流)和FileOutputStream(文件输出流)可知,在文件拷贝的时候,其文件数据的流转顺序为:
文件→FileInputStream→字节数组→FileOutputStream→文件Copy;
●使用缓冲流的情况:
文件→FileInputStream→字节数组→缓冲区→FileOutputStream→文件Copy;
●缓冲流为什么能够提高读写速度:(有几种说法如下,有点笼统)
(1)文件的读写包括:文件的I/O和其他操作,没有缓冲区时,I/O和其他操作都是CPU的工作(CPU采用DMA的方式去执行I/O操作);设了缓冲区后,CPU 将I/O操作交给专门的DMA控制器去做,当缓冲区填满后,DMA控制器会通知CPU,以让其完成其他操作;DMA控制器比CPU更善于做I/O与内存数据交换,从而提升效率。
(2)文件读写是需要和硬件打交道的,每次读写就是一次I/O操作,而io操作是很费时的。而其中,又包括读和写;没有缓冲区时,是读一点(byte字节数组)写一点;有缓冲区后,是读一点,往缓冲区里存一点,如此多次读,直到将缓冲区存满,缓冲区满了后,再将这些数据一次性地写入到文件中。所以,可以这样认为,缓冲区减少了写的次数,从而提升效率。
(2.1)通过本篇博客的例子中,缓冲流的使用。可以看出,读的时候,还是一个字节数组一个字节数组的读,把读到的数据存到缓冲区中,然后写的时候,看起来也是一个字节数组一个字节数组的写,好像并没有看到缓冲区在哪儿,,,,,好吧,为了说服自己,暂时认为缓冲区对用户(在程序代码中)不可见吧。
二:缓冲流属性和方法简介
BufferedInputStream:缓冲输入流
属性:

构造方法:
缓冲输入流的构建需要传入一个文件输入流作为参数;

常用方法:

……………………………………………………
BufferedOutputStream:缓冲输出流
属性:

构造方法:
缓冲输出流的构建需要传入一个文件输出流作为参数;

常用方法:
注:close()方法会强制清空缓冲区内容,这也会把缓冲区中的内容写入到文件中。

三:缓冲流在文件复制中的示例
(1)使用缓冲流复制文件:使用“#######”标识的语句为缓冲流新增内容;
(2)为了使代码简洁,也可写成这样:

public class FileOutputDemo2 {
public static void main(String[] args) {
// 文件拷贝:图片文件的复制粘贴,读取和写入
// (1)创建输入流对象,输出对象
FileInputStream fis;
FileOutputStream fos;
BufferedInputStream bis;
BufferedOutputStream bos;
try {
// (2)实例化输入流对象指向待复制文件;实例化输出对象,参数为复制后文件的全路径;
fis = new FileInputStream("video.mp4");
// (2.1)构造缓冲输入流
bis = new BufferedInputStream(fis); // 缓冲输入流#######
fos = new FileOutputStream("videoCopy.mp4");
// (2.2)构造缓冲输出流
bos = new BufferedOutputStream(fos); // 缓冲输出流#######
// (3)n存放读方法的返回值,如果为-1代表已经读到文件末尾了;
int n = 0;
// (4)定义一个字节数组,存放读取到的数据;这个数组得大一点;
byte[] b = new byte[1024];
long startTime = System.currentTimeMillis(); // 对比运行时间用 #######
// (5)读取内容,并同时将读取到的内容写出来;这儿是每读1024个字节就写一下,即读一点写一点,直到全部复制完;
// (5.1)调用缓冲输入流的read()方法
while((n = bis.read(b))!= -1){ // 缓冲流的read方法和write方法和文件流的并无二致#######
// (5.2)调用缓冲输出流的write()方法
bos.write(b,0,n); // 将读取到的内容写到fos这个文件流对象对应的文件中去;
}
// (6)关闭输入流、输出流;
bos.flush();
long endTime = System.currentTimeMillis();// 对比运行时间用 #######
System.out.println(endTime - startTime);
fis.close();
fos.close();
bis.close();
bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e){ // 注:这几文件的读写,IOException是必须抛出的,当成常识记住就行…
e.printStackTrace();
}
}
}
其运行时间为:

上篇博客中未使用缓冲流复制文件时:
(下面代码可以不用看和上篇博客内容一样)
public class BufferedDemo1 {
public static void main(String[] args) {
// 文件拷贝:图片文件的复制粘贴,读取和写入
// (1)创建输入流对象,输出对象
FileInputStream fis;
FileOutputStream fos;
BufferedInputStream bis;
BufferedOutputStream bos;
try {
// (2)实例化输入流对象指向待复制文件;实例化输出对象,参数为复制后文件的全路径;
fis = new FileInputStream("video.mp4");
//bis = new BufferedInputStream(fis); // 缓冲输入流
fos = new FileOutputStream("videoCopy.mp4");
//bos = new BufferedOutputStream(fos); // 缓冲输出流
// (3)n存放读方法的返回值,如果为-1代表已经读到文件末尾了;
int n = 0;
// (4)定义一个字节数组,存放读取到的数据;这个数组得大一点;
byte[] b = new byte[1024];
long startTime = System.currentTimeMillis();
// (5)读取内容,并同时将读取到的内容写出来;这儿是每读1024个字节就写一下,即读一点写一点,直到全部复制完;
while((n = fis.read(b))!= -1){
fos.write(b,0,n); // 将读取到的内容写到fos这个文件流对象对应的文件中去;
}
// (6)关闭输入流、输出流;
//bos.flush();
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
fis.close();
fos.close();
//bis.close();
//bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e){ // 注:这几文件的读写,IOException是必须抛出的,当成常识记住就行…
e.printStackTrace();
}
}
}
运行时间:可以发现,缓冲流对效率的提升还是挺明显的。

918

被折叠的 条评论
为什么被折叠?



