欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java NIO 入门(三)从理论到实践:使用NIO读写

程序员文章站 2022-07-13 17:01:24
...
Java NIO 入门(三)从理论到实践:使用NIO读写
guibin.beijing@gmail.com

概述
读和写是最基础的IO处理。从Channel中读是非常简单的,我们只要创建一个Buffer,然后要求Channel往Buffer中读数据。写也很简单,也需要创建一个Buffer,把要写的数据填充到Buffer中,然后要求Channel把Buffer中的数据写出去。

在这节中,我们学习使用JAVA程序来读写数据,顺便浏览一下NIO的主要组件(Buffer,Channel以及相关的方法)并且看看他们在读写数据时如何交互,在后面的章节中我们将依次查看每个组件的细节。

从文件中读数据
在第一个练习中,我们首先从文件中读取一些数据。如果使用老的IO,只需要简单的创建FileInputStream,然后从中读取数据。在NIO中,事情变得有些不同了,首先需要从FileInputStream中获取Channel对象,然后使用这个Channel去读文件。

在NIO系统中任何时刻执行一个读操作时,都要从Channel中读,但不是直接从Channel中读。由于所有的数据都需要通过Buffer承载,所以需首先从Channel中把数据读进Buffer。

因此,从文件中读数据一共有三步:
  • 从FileInputStream中获取Channel
  • 创建Buffer
  • 从Channel中把数据读入Buffer

下面我们仔细看看具体时如何工作的。

三步简单的工作
第一步获取Channel。从FileInputStream中获取Channel。
FileInputStream fin = new FileInputStream( "readandshow.txt" ); 
FileChannel fc = fin.getChannel();

第二步创建Buffer
ByteBuffer buffer = ByteBuffer.allocate( 1024 );

最后一步,将文件内容通过Channel读入Buffer中
fc.read( buffer );

你一定发现,在这里,并没有告诉Channel把多少内容读进Buffer。在每个Buffer中都有一套完整的内部计数系统来跟踪已经读了多少数据了,Buffer中还剩多少空间。关于Buffer的计数系统在随后的“Buffer内部原理”中讲解。

写文件
使用NIO写文件和读文件非常类似。我们还是从FileOutputStream中获取Channel。
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" );
FileChannel fc = fout.getChannel();

下一步还是创建Buffer并且把数据放到Buffer中。在这种情况下数据将从一个叫做message的数组中取出,这个数组中包含了字符串ASCII码的字节。(The buffer.flip() 和 buffer.put()在后面讲解)
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
for (int i=0; i<message.length; ++i) { 
  buffer.put( message[i] );
} 
buffer.flip();

最后一步就是把Buffer写出去。
fc.write( buffer );


再次注意,我们没有必要告诉Channel总共要写多少数据,Buffer的内部计数系统会跟踪已经写了多少数据了,还剩多少空间可以使用。

边读边写
下面看看当我们把读和写结合起来会发生什么。这个练习程序的名称叫CopyFile.java,用来从一个文件拷贝全部数据到另一个文件。Copy.java包含了三个基本的操作:
  • 首先创建Buffer
  • 然后从源文件把数据读入Buffer
  • 最后把Buffer写入目的文件

程序重复的进行读写、读写,直到文件读完。

CopyFile程序能够看到如何检查程序的状态,以及如何使用clear(),flip()方法重置Buffer,如何读数据从一个Channel到另一个Channel。

运行CopyFile例子
因为Buffer跟踪了自己的内部数据,因此CopyFile程序的内部循环非常简单,如下:
fcin.read( buffer ); 
fcout.write( buffer );

首先数据从输入Channel中读入Buffer,然后把数据写出到输出Channel中。因为输入和输出分别对应于两个文件,因此是两个Channel。

检查读文件的状态
下一步,当我们在拷贝时需要检查读文件的状态。当没有数据可读时即执行完毕,这个状态可以通过read()方法返回-1来判断,如下:
int r = fcin.read( buffer );
if (r==-1) { 
  break;
}


重置Buffer
最后,在从Channel将数据读入Buffer前调用clear()方法,相似的,在将Buffer写入输出Channel之前调用flip()方法。
buffer.clear(); 
int r = fcin.read( buffer );

if (r==-1) { 
  break;
}

buffer.flip(); 
fcout.write( buffer );


clear()方法重置了Buffer,使其准备好能够将读入的数据放入Buffer中。flip()方法使得Buffer准备好把Buffer中的数据写入Channel。

本文参考自http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf


相关标签: JAVA NIO IO