Java NIO 详解(一) (2)

IO中的读和写,对应的是数据和Stream,NIO中的读和写,则对应的就是通道和缓冲区。NIO中从通道中读取:创建一个缓冲区,然后让通道读取数据到缓冲区。NIO写入数据到通道:创建一个缓冲区,用数据填充它,然后让通道用这些数据来执行写入。

3.1 从文件中读取

我们已经知道,在NIO系统中,任何时候执行一个读操作,您都是从Channel中读取,而您不是直接从Channel中读取数据,因为所有的数据都必须用Buffer来封装,所以您应该是从Channel读取数据到Buffer。

因此,如果从文件读取数据的话,需要如下三步:

从FileInputStream获取Channel

创建Buffer

从Channel读取数据到Buffer

下面我们看一下具体过程:
第一步:获取通道

FileInputStream fin = new FileInputStream( "readandshow.txt" ); FileChannel fc = fin.getChannel(); 123

第二步:创建缓冲区

ByteBuffer buffer = ByteBuffer.allocate( 1024 ); 12

第三步:将数据从通道读到缓冲区

fc.read( buffer ); 12 3.2 写入数据到文件

类似于从文件读数据,
第一步:获取一个通道

FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" ); FileChannel fc = fout.getChannel(); 123

第二步:创建缓冲区,将数据放入缓冲区

ByteBuffer buffer = ByteBuffer.allocate( 1024 ); for (int i=0; i<message.length; ++i) { buffer.put( message[i] ); } buffer.flip(); 1234567

第三步:把缓冲区数据写入通道中

fc.write( buffer ); 12 3.3 读写结合

CopyFile是一个非常好的读写结合的例子,我们将通过CopyFile这个实力让大家体会NIO的操作过程。CopyFile执行三个基本的操作:创建一个Buffer,然后从源文件读取数据到缓冲区,然后再将缓冲区写入目标文件。

/** * 用java NIO api拷贝文件 * @param src * @param dst * @throws IOException */ public static void copyFileUseNIO(String src,String dst) throws IOException{ //声明源文件和目标文件 FileInputStream fi=new FileInputStream(new File(src)); FileOutputStream fo=new FileOutputStream(new File(dst)); //获得传输通道channel FileChannel inChannel=fi.getChannel(); FileChannel outChannel=fo.getChannel(); //获得容器buffer ByteBuffer buffer=ByteBuffer.allocate(1024); while(true){ //判断是否读完文件 int eof =inChannel.read(buffer); if(eof==-1){ break; } //重设一下buffer的position=0,limit=position buffer.flip(); //开始写 outChannel.write(buffer); //写完要重置buffer,重设position=0,limit=capacity buffer.clear(); } inChannel.close(); outChannel.close(); fi.close(); fo.close(); } 12345678910111213141516171819202122232425262728293031323334 四、需要注意的点

上面程序中有三个地方需要注意

4.1 检查状态

当没有更多的数据时,拷贝就算完成,此时 read() 方法会返回 -1 ,我们可以根据这个方法判断是否读完。

int r= fcin.read( buffer ); if (r==-1) { break; } 12345 4.2 Buffer类的flip、clear方法 控制buffer状态的三个变量

position:跟踪已经写了多少数据或读了多少数据,它指向的是下一个字节来自哪个位置

limit:代表还有多少数据可以取出或还有多少空间可以写入,它的值小于等于capacity。

capacity:代表缓冲区的最大容量,一般新建一个缓冲区的时候,limit的值和capacity的值默认是相等的。

flip、clear这两个方法便是用来设置这些值的。

flip方法

我们先看一下flip的源码:

public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }

Java NIO 详解(一)

在上面的FileCopy程序中,写入数据之前我们调用了buffer.flip();方法,这个方法把当前的指针位置position设置成了limit,再将当前指针position指向数据的最开始端,我们现在可以将数据从缓冲区写入通道了。 position 被设置为 0,这意味着我们得到的下一个字节是第一个字节。 limit 已被设置为原来的 position,这意味着它包括以前读到的所有字节,并且一个字节也不多。

clear方法

先看一下clear的源码:

public final Buffer clear() { position = 0; limit = capacity; mark = -1; return this; }

Java NIO 详解(一)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgfwgz.html