IO流之缓冲区

IO流(BufferedInputStream和BufferOutputStream拷贝)

  • A:缓冲思想
       字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,    这是加入了数组这样的缓冲区效果,java本身在设计的时候,
      * 也考虑到了这样的设计思想,所以提供了字节缓冲区流
  • B.BufferedInputStream
       BufferedInputStream内置了一个缓冲区(数组)    从BufferedInputStream中读取一个字节时
       BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个    程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
      * 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
  • C.BufferedOutputStream
       BufferedOutputStream也内置了一个缓冲区(数组)    程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
      * 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

字符读取流缓冲区:

特有功能:readLine();//读取一行,返回值是字符串,读到结尾是null

举例:
{
//创建一个读取流对象和文件相关联
FileReader fr = new FileReader(“buf.txt”);

//将字符读取流对象作为参数传递给缓冲对象的构造函数。
BufferedReader bufr = new BufferedRead();

//读取一行
Sting line = null;
while( (line = bufr.readLine() )!=null)
{
System.out.println(line);
}

}

字符流的缓冲区:

因为缓冲区技术是为流技术存在的,所以建立缓冲区之前必须先有流对象。然后把流对象作为参数传给缓冲对象的构造函数,注意,缓冲类是没有空参数构造函数的,他必须在流对象的前提下创建。原理就是对象中封装了数组。

  • 缓冲区要结合流才可以使用
  • 在流的基础上对流的功能进行了增强

对应类:
BufferedWriter
BufferedReader

** 特有功能:newLine()//增加一个行分隔符,JAVA中封装了各种系统的换行字符。

举例:
{
//创建字符写入流对象
FileWriter fw = new FileWriter(“buf.txt”);

//将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedWriter bufw = new BufferedWriter(fw);

//换行
bufw.wirte(“abc”);
bufw.newLine();

//刷新
bufw.flush();

//其实关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();
}


缓冲区提高效率的原理

调用I\O操作的时候,实际上还是一个一个的读或者写。
关键就在,
CPU只有一个,不论是几个核心。
CPU在系统调用时,会不会还要参与主要操作?参与多次就会花更多的时间。

系统调用时,若不用缓冲,CPU会酌情考虑使用中断。
此时CPU是主动地,每个周期中都要花去一部分去询问I\O设备是否读完数据,
这段时间CPU不能做任何其他的事情(至少负责执行这段模块的核不能)。
所以,调用一次读了一个字,通报一次,CPU腾出时间处理一次。

而设置缓冲,CPU通常会使用 DMA 方式去执行 I\O 操作。
CPU 将这个工作交给DMA控制器来做,自己腾出时间做其他的事,
当DMA完成工作时,DMA会主动告诉CPU“操作完成”。
这时,CPU接管后续工作。在此,CPU 是被动的。
DMA是专门做 I\O 与内存数据交换的,不仅自身效率高,也节约了CPU时间,CPU在DMA开始和结束时做了一些设置罢了。
所以,调用一次,不必通报CPU,等缓冲区满了,DMA 会对C PU 说 “嘿,伙计!快过来看看,把他们都搬走吧”。

综上,设置缓冲,就建立了数据块,使得DMA执行更方便,CPU也有空闲,而不是呆呆地候着I\O数据读来。从微观角度来说,设置缓冲效率要高很多。尽管,不能从这个程序上看出来。 几万字的读写\就能看到差距