跟我学NIO(入门实例)

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

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

从文件中读取

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

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

读取文件步骤:

(1)从FileInputStream获取Channel

FileInputStream fileInputStream = newFileInputStream("test.txt");
FileChannel fileChannel = fileInputStream.getChannel();

(2)创建Buffer

ByteBuffer buffer = ByteBuffer.allocate(1024);

(3)将数据从Channel读到Buffer中

fileChannel.read(buffer);

注意:我们不需要告诉通道要读多少数据到缓冲区中。每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据以及还有多少空间可以容纳更多的数据(请查看缓冲区内部实现原理)。



写入文件步骤:

(1)在NI/O中写入文件类似于从文件中读取。首先从FileOutputStream获取一个通道。

FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
FileChannel fileChannel = fileOutputStream.getChannel();

(2)创建一个缓冲区并在其中放入一些数据-在这里,数据将从一个名为message的数组中取出,这个数组包含字符串"hello! NI/O"的ASCII字节。

byte[] message = new String("hello! NI/O").getBytes();
ByteBuffer buffer = ByteBuffer.allocate(1024);
for(int i=0,len=message.length; i<len; ++i){
    buffer.put(message[i]);
}
buffer.flip();

(3)将缓存的数据写入到文件中。

fileChannel.write(buffer);

注意:在这里同样不需要告诉通道要写入多数据。缓冲区的内部统计机制会跟踪它包含多少数据以及还有多少数据要写入。

读写结合

我们以一个名为CopyFile.java的程序来对读写进行说明,CopyFile.java将一个文件的所有内容拷贝到另一个文件中。CopyFile.java执行三个基本操作:首先创建一个Buffer,然后从源文件中将数据读到这个缓冲区中,然后将缓冲区写入目标文件。这个程序不断重复—读、写、读、写—直到源文件结束。

CopyFile程序让您看到我们如何检查操作的状态,以及如何使用clear()和flip()方法重设缓冲区,并准备缓冲区以便将新读取的数据写到另一个通道中。

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class CopyFile
{
  static public void main( String args[] ) throws Exception {
    if (args.length<2) {
      System.err.println( "用法: java CopyFile 输入文件 输出文件" );
      System.exit( 1 );
    }
    String infile = args[0];
    String outfile = args[1];
    FileInputStream fin = new FileInputStream( infile );
    FileOutputStream fout = new FileOutputStream( outfile );
    FileChannel fcin = fin.getChannel();
    FileChannel fcout = fout.getChannel();
    ByteBuffer buffer = ByteBuffer.allocate( 1024 );
    while (true) {
      buffer.clear();
      int r = fcin.read( buffer );
      if ( r == -1 ) {
        break;
      }
      buffer.flip();
      fcout.write( buffer );
    }
  }
}

因为缓冲区会跟踪它自己的数据,所以CopyFile程序的内部循环(innerloop)非常简单,如下所示:

// 将数据从输入通道fcin中读入缓冲区
fcin.read(buffer);
// 将这些缓冲区中的数据写到输出通道fcout
fcout.write(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() 方法重设缓冲区,使它可以接受读入的数据。它将限制设置为容量大小,将位置设置为 0。

flip() 方法让缓冲区可以将新读入的数据写入另一个通道。它将限制设置为当前位置,然后将位置设置为 0。

所谓天才,只不过是把别人喝咖啡的功夫都用在工作上了。——鲁迅
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号