Java NIO异步文件通道原理及用法解析
在Java7,AsynchronousFileChannel被添加到了JavaNIO中。使用AsynchronousFileChannel可以实现异步地读取和写入文件数据。
创建一个AsynchronousFileChannel
我们可以使用AsynchronousFileChannel提供的静态方法open()创建它。示例代码如下:
Pathpath=Paths.get("data/test.xml");
AsynchronousFileChannelfileChannel=
AsynchronousFileChannel.open(path,StandardOpenOption.READ);
第一个参数是一个PATH的对像实例,它指向了那个与AsynchronousFileChannel相关联的文件。
第二个参数是一个或多个操作选项,它决定了AsynchronousFileChannel将对目标文件做何种操作。示例代码中我们使用了StandardOpenOption.READ,它表明我们将要对目标文件进行读操作。
读取数据
AsynchronousFileChannel提供了两种读取数据的方式,都是调用它本身的read()方法。下面将对两种方式进行介绍。
使用Futrue读取数据
第一种反式是调用AsynchronousFileChannel的read()方法,该方法反回一个Future类型的对象。
Futureoperation=fileChannelread(buffer,0);
第一个参数是ByteBuffer,从AsynchronousFileChannel中读取的数据先写入这个ByteBuffer。
第二个参数表示从文件读取数据的开始位置。
此read()方法会立即返回,即使整个读的过程还没有完全结束。我们可以通过operation.isDone()来检查读取是否完成。这里的operation是上面调用read()方法返回的Future类型的实例。下面是一段详细的代码示例:
AsynchronousFileChannelfileChannel= AsynchronousFileChannel.open(path,StandardOpenOption.READ); ByteBufferbuffer=ByteBuffer.allocate(1024); longposition=0; Futureoperation=fileChannel.read(buffer,position); while(!operation.isDone()); buffer.flip(); byte[]data=newbyte[buffer.limit()]; buffer.get(data); System.out.println(newString(data)); buffer.clear();
上面的程序首先创建了一个AsynchronousFileChannel对象,然后调用它的read()方法返回一个Future。其中read()方法需要两个参数,一个是ByteBuffer,另一个是读取文件的开始位置。然后通过循环调用isDone()方法检测读取过程是否完成,完成后isDone()方法将返回true。尽管这样让cpu空转了一会,但是我们还是应该等读取操作完成后再进行后续的步骤。
一旦读取完成,数据被存储到ByteBuffer,然后将数据转化为字符串既而输出。
使用CompletionHandler读取数据
第二种读取数据的方式是调用AsynchronousFileChannel的另一个重载read()方法,改方法需要一个CompletionHandler作为参数。下面是代码示例:
fileChannel.read(buffer,position,buffer,newCompletionHandler(){ @Override publicvoidcompleted(Integerresult,ByteBufferattachment){ System.out.println("result="+result); attachment.flip(); byte[]data=newbyte[attachment.limit()]; attachment.get(data); System.out.println(newString(data)); attachment.clear(); } @Override publicvoidfailed(Throwableexc,ByteBufferattachment){ } });
一旦读取操作完成,CompletionHandler的complete()方法将会被调用。它的第一个参数是个Integer类型,表示读取的字节数。第二个参数attachment是ByteBuffer类型的,用来存储读取的数据。它其实就是由read()方法的第三个参数。当前示例中,我们选用ByteBuffer来存储数据,其实我们也可以选用其他的类型。
读取失败的时候,CompletionHandler的failed()方法会被调用。
写入数据
就像读取一样,我们同样有两种方式向AsynchronousFileChannel写入数据。我们可以调用它的2个重载的write()方法。下面我们将分别加以介绍。
使用Future读取数据
AsynchronousFileChannel也可以异步写入数据。下面是一个完整的写入示例:
AsynchronousFileChannel也可以异步写入数据。下面是一个完整的写入示例: Pathpath=Paths.get("data/test-write.txt"); AsynchronousFileChannelfileChannel= AsynchronousFileChannel.open(path,StandardOpenOption.WRITE); ByteBufferbuffer=ByteBuffer.allocate(1024); longposition=0; buffer.put("testdata".getBytes()); buffer.flip(); Futureoperation=fileChannel.write(buffer,position); buffer.clear(); while(!operation.isDone()); System.out.println("Writedone");
首先实例化一个写入模式的AsynchronousFileChannel,然后创建一个ByteBuffer并写入一些数据。再然后将数据写入文件。最后,检查返回的Future,看是否写入完成。
注意,写入目标文件要提前创建好,如果它不存在的话,writh()方法会抛出一个java.nio.file.NoSuchFileException。
我们可以用以下方式来解决这一问题:
if(!Files.exists(path)){
Files.createFile(path);
}
使用CompletionHandler写入数据
我们也可以使用CompletionHandler代替Future向AsynchronousFileChannel写入数据,这种方式可以更加直接的知道写入过程是否完成。下面是示例程序:
Pathpath=Paths.get("data/test-write.txt"); if(!Files.exists(path)){ Files.createFile(path); } AsynchronousFileChannelfileChannel= AsynchronousFileChannel.open(path,StandardOpenOption.WRITE); ByteBufferbuffer=ByteBuffer.allocate(1024); longposition=0; buffer.put("testdata".getBytes()); buffer.flip(); fileChannel.write(buffer,position,buffer,newCompletionHandler(){ @Override publicvoidcompleted(Integerresult,ByteBufferattachment){ System.out.println("byteswritten:"+result); } @Override publicvoidfailed(Throwableexc,ByteBufferattachment){ System.out.println("Writefailed"); exc.printStackTrace(); } });
当写入程序完成时,CompletionHandler的completed()方法将会被调用,相反的如果写入失败则会调用failed()方法。
要留意CompletionHandler的方法的参数attachemnt是怎么使用的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。