转载

java 流 I/O 与 块 I/O 比较

操作系统要移动的是大块数据(缓冲区), 这往往是在硬件直接存储器存取 (DMA) 的协助下完成的.

例如硬盘操作, 磁盘控制器通过 DMA 直接将数据写入内核的内存缓冲区. 一旦磁盘控制器完成了缓存的填写, 内核从内核空间的临时缓存拷贝数据到用户控件缓存中.

所以操作系统是以卡车的形式拷贝数据, 但是 Java 基于流的 I/O 模型, 是一铲子一铲子的加工数据.

面向流I/O的系统: 一次处理一个字节的数据. 一个输入流每次会读入一个字节的数据,一个输出流同样每次次消费一个字节的数据. 例如 Java 中的 SocketInputStreamFileInputStream 都是一次读取一个.

虽然你读取的数据时, 可能会使用如下代码:

byte[] receiveBuffer = new byte[128];
String clientMessage = "";
if((receiveBytes=in.read(receiveBuffer))!=-1) {

这里虽然指定了读取数据的大小, 但是要注意, 在读取时, 并不是一次性全部读取完成, 而是一个一个进行读取, 读取的次数就是数组的大小.

面向块I/O的系统: 以块为单位处理数据. 每个操作步骤会生成或消费一个块的数据.

先创建一个缓冲区

// 缓冲区的大小
private final static int BUFFER_SIZE = 1024;

// 缓冲区
private ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);

然后使用类似以下代码来读取数据到缓冲区.

int len = 0;
while ((len = socketChannel.read(buffer)) > 0) {

也就是说, 直接读取缓冲区大小的一块数据, 保存到缓冲区中.

值得注意的是: 虽然创建缓冲区, 和上面创建的 byte[] 数组作用是一样的, 都是用来存储数据. 但是千万不要搞混了, 流 IO 和 块 IO 的底层处理方式不一样的.

原文  https://segmentfault.com/a/1190000020424993
正文到此结束
Loading...