现在的位置: 首页 > 综合 > 正文

Java NIO学习2(一个例子引起的故事)

2016年12月18日 ⁄ 综合 ⁄ 共 1957字 ⁄ 字号 评论关闭

先来个nio的例子,不然直接上技术太空泛了!

读和写是 I/O 的基本过程。从一个通道中读取很简单:只需创建一个缓冲区,然后让通道将数据读到这个缓冲区中。写入也相当简单:创建一个缓冲区,用数据填充它,然后让通道用这些数据来执行写入操作。

我们将从一个文件中读取一些数据。如果使用原来的 I/O,那么我们只需创建一个FileInputStream 并从它那里读取。而在 NIO 中,情况稍有不同:我们首先从 FileInputStream 获取一个FileInputStream 对象,然后使用这个通道来读取数据。

在 NIO 系统中,任何时候执行一个读操作,您都是从通道中读取,但是您不是 直接从通道读取。因为所有数据最终都驻留在缓冲区中,所以您是从通道读到缓冲区中。

因此读取文件涉及三个步骤:(1) 从 FileInputStream 获取 Channel,(2) 创建 Buffer,(3) 将数据从 Channel读到 Buffer 中。

下面代码是将: copy.txt文件中的内容复制到 paste.txt文件中

		//得到源文件与目标文件的路径
		String 	copyPath = Demo1.class.getResource("copy.txt").getPath();
		String 	pastePath = Demo1.class.getResource("paste.txt").getPath();
		
		FileInputStream ins = new FileInputStream(new File(copyPath));
		FileOutputStream out = new FileOutputStream(new File(pastePath));
		//从输入输出流中得到  channel
		FileChannel fIns = ins.getChannel();
		FileChannel fOut = out.getChannel();
		//创建一个Buffer  大小为1024
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		
		while(true){
			//清空缓冲区
			buffer.clear();
			//读输入到缓冲区
			int n = fIns.read(buffer);
			if(n == -1){
				break;
			}
			// flip方法让缓冲区可以将新读入的数据写入另一个通道  
			buffer.flip();
			// 从输出通道中将数据写入缓冲区  
			fOut.write(buffer);
		}
		
		System.out.println("over !");

三个容易的步骤

第一步:是获取通道。我们从 FileInputStream 获取通道:
FileInputStream fin = new FileInputStream( "readandshow.txt" );
FileChannel fc = fin.getChannel();

下一步是创建缓冲区:
ByteBuffer buffer = ByteBuffer.allocate( 1024 );

最后,需要将数据从通道读到缓冲区中,如下所示:
fc.read( buffer );
您会注意到,我们不需要告诉通道要读 多少数据到缓冲区中。每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据以及还有多少空间可以容纳更多的数据。

检查状态
下一步是检查拷贝何时完成。当没有更多的数据时,拷贝就算完成,并且可以在 read() 方法返回 -1 是判断这一点,
如下所示:
int r = fcin.read( buffer );
if (r==-1) {
break;
}

重设缓冲区
最后,在从输入通道读入缓冲区之前,我们调用 clear() 方法。同样,在将缓冲区写入输出通道之前,我们调用 flip()
方法,如下所示:
buffer.clear();
int r = fcin.read( buffer );
if (r==-1) {
break;
}
buffer.flip();
fcout.write( buffer );
clear() 方法重设缓冲区,使它可以接受读入的数据。 flip() 方法让缓冲区可以将新读入的数据写入另一个通道。

小结:

在Java nio中  有两个核心对象:缓冲区 
通道

1 通道channel: 到达任何目的(或者来自任何地方)的所有数据 都必须通过一个channel对象

上面的代码中 ,首先从copy中 得到数据,要用到Inputstream的getChannel方法得到channel对象 ,同样写入paste文件需要outputStream的channel对象

2 缓冲区 buffer 是一个容器对象,发送给一个通道的所有对象都必须首先放到缓冲区中,同样从通道中读取的时候也要首先读到缓冲区中。

由代码可以看出,首先从copy文件中读到buffer中,然后在把buffer内容写入到paste文件中

ps:缓冲区实质上是一个数组,通常是字节数组,也可能使用其他的数组。

抱歉!评论已关闭.