通道(Channel)和缓存区(Buffer)。
通道是对nio包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。通道与流的不同之处在于通道是双向的。
读和写是 I/O 的基本过程。从一个通道中读取很简单:只需创建一个缓冲区,然后让通道将数据读到这个缓冲区中。写入也相当简单:创建一个缓冲区,用数据填充它,然后让通道用这些数据来执行写入操作。
读取文件。如果使用原来的 I/O,那么我们只需创建一个 FileInputStream
并从它那里读取。读取文件涉及三个步骤:(1) 从 FileInputStream
获取 Channel
,(2) 创建 Buffer
,(3) 将数据从 Channel
读到 Buffer
中。
下面是一个读取文件的例子:
第一步是获取通道。我们从 FileInputStream
获取通道:
FileInputStream fin = new FileInputStream( "readandshow.txt" );
FileChannel fc = fin.getChannel();
下一步是创建缓冲区:
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
最后,需要将数据从通道读到缓冲区中,如下所示:
fc.read( buffer );
我们不需要告诉通道要读 多少数据 到缓冲区中。每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据以及还有多少空间可以容纳更多的数据。
因为缓冲区会跟踪它自己的数据,所以 CopyFile 程序的内部循环 (inner loop) 非常简单,如下所示:
fcin.read( buffer );
在从输入通道读入缓冲区之前,我们调用
fcout.write( buffer );clear()
方法。同样,在将缓冲区写入输出通道之前,我们调用flip()
方法clear()
方法重设缓冲区,使它可以接受读入的数据。flip()
方法让缓冲区可以将新读入的数据写入另一个通道。