当前位置:编程学习 > JAVA >>

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

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。
Java代码 
FileInputStream fin = new FileInputStream( "readandshow.txt" );  
FileChannel fc = fin.getChannel(); 

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

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

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

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

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

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


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

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

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

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

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

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

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


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

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


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

作者“guibin”
 

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,