关于java的io读写,缓冲区是如何提高读写效率的???

2024-11-02 06:26:41
推荐回答(4个)
回答1:

给你一个例子自己看看吧,加深理解

我们知道Java中一般的输入输出流类都是用单字节的读取方法来进行I/O操作的,也就是说每次只读写一个字节的数据,这种方法显然繁琐低效。如果从设备读取10M的文件,每次读取一个字节,完成操作将需要做10M/次I/O操作,I/O操作又是一件相当耗时的事情,无疑在很大程度上降低了系统的性能。

Java中专门提供提高I/O效率的缓冲类,这好比在数据读写时提供一个临时缓冲区,每次读取一个缓冲区大小的数据,将这数据库一次性写入目标设备。下图中分别为两种读取方式。

举个简单例子,在A地有10000本书需要搬到B地,如果一次搬1本,需要10000次。如果每次取1000本放到一个货车上,运到B地,需要10次完成。货车相当于是缓存区。同样道理,开设一个数据缓存区每次读取一数据块对于提高读取效率有显著提升。下面用一个具体代码示例来表示二者的性能差别。

Java代码
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TestBuffer {

public static void main(String args[]) throws IOException {
String from = "f:/1.MP3";
System.out.println(from);
long startTime1 = System.currentTimeMillis();
TestBuffer.readWriteWithBuffer(from, "f:/2.MP3");
long endTime1 = System.currentTimeMillis();
System.out.println("使用缓冲区读取耗时:" + (endTime1 - startTime1) +"ms");
long startTime = System.currentTimeMillis();
TestBuffer.readWrite(from,"f:/3.MP3");
long endTime = System.currentTimeMillis();
System.out.println("直接读取耗时:" + (endTime - startTime) +"ms");

}

public static void readWrite(String from, String to) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
while (true) {
int data = in.read();
if (data == -1) {
break;
}
out.write(data);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}

/***************************************************************************
* 使用缓存区读写文件
* @param from
* @param to
* @throws IOException
*/
public static void readWriteWithBuffer(String from, String to)
throws IOException {
InputStream inBuffer = null;
OutputStream outBuffer = null;
try {
inBuffer = new BufferedInputStream(new FileInputStream(from));
outBuffer = new BufferedOutputStream(new FileOutputStream(to));
while (true) {
int data = inBuffer.read();
if (data == -1) {
break;
}
outBuffer.write(data);
}
} finally {
if (inBuffer != null) {
inBuffer.close();
}
if (outBuffer != null) {
outBuffer.close();
}
}
}

}
运行例子时会根据mp3文件的大小决定运行时间的长短,尽量使用小一点的mp3文件,运行时需耐心等待一段时间

回答2:

理解是对的。
调用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数据读来。从微观角度来说,设置缓冲效率要高很多。尽管,不能从这个程序上看出来。 几万字的读写\就能看到差距

回答3:

打个比方,比如你带兵打仗,需要军火支应,从仓库搬运军火的数量和批次是不变的,那么你是会一次搬出需要的所有军火前去打仗,还是在打仗的过程中派人搬一箱,没了再搬一箱呢?显然是第一种方法,但是一次全部拿出来,往哪里放?这时就需要一辆卡车(缓冲区)用来存放并运输,这样,一线战士(应用程序)就不用担心弹药不足从而提高作战效率,库房管理者(cpu)也不用担心会有人回来提调军火而一直守在库房旁边,他完全可以去做别的工作了。这样说,不知道你能明白不?

个人意见,希望对你有用!

回答4:

换IE6试一下,大部分bs应用都是起码对IE6进行兼容。如果你的系统没有装IE6,你可以用一些IE6内核的浏览器,例如 遨游,360浏览器,腾讯tt浏览器等等~