AsynchronousFileChannel如何读取大文件? Path file=Path.get(“c:/large.log”); AsynchronousFileChannel=AsynchronousFileChannel.open(文件); 最终ByteBuffer缓冲区=ByteBuffer.allocate(1000); 通道读取(缓冲区,0,缓冲区, 新的CompletionHandler(){ 已完成公共作废(整数结果,ByteBuffer附件){ System.out.println(新字符串(buffer.array()); } });
通过这种方式,我可以从large.log读取第一个1000字节。如果我不想像ByteBuffer.allocate(1000*1000)那样分配更大的字节数组,我如何读取下面的日志。因为我认为这会导致记忆的流失 有人能给我示例代码吗? 谢谢AsynchronousFileChannel如何读取大文件? Path file=Path.get(“c:/large.log”); AsynchronousFileChannel=AsynchronousFileChannel.open(文件); 最终ByteBuffer缓冲区=ByteBuffer.allocate(1000); 通道读取(缓冲区,0,缓冲区, 新的CompletionHandler(){ 已完成公共作废(整数结果,ByteBuffer附件){ System.out.println(新字符串(buffer.array()); } });,io,java-7,nio2,Io,Java 7,Nio2,通过这种方式,我可以从large.log读取第一个1000字节。如果我不想像ByteBuffer.allocate(1000*1000)那样分配更大的字节数组,我如何读取下面的日志。因为我认为这会导致记忆的流失 有人能给我示例代码吗? 谢谢 ps:我可以使用JIO循环读取大文件,因为我可以检查java.io.BufferedReader.read()的返回值。但是我不知道如何使用NIO2。如果文件中还有剩余内容,请在completionHandler中启动另一次读取。但我会使用比1000大得多的
ps:我可以使用JIO循环读取大文件,因为我可以检查java.io.BufferedReader.read()的返回值。但是我不知道如何使用NIO2。如果文件中还有剩余内容,请在completionHandler中启动另一次读取。但我会使用比1000大得多的缓冲区,至少8192个。这里有一个可行的方法 您需要注意以下几点:
buffer.array()
作为输出。我必须使用buffer.clear()重置位置,以便异步读取将看到有1000个备用字节,但这并不能从数组中清除现有数据。因此,当您在文件末尾时,如果读取的字节少于1000字节,它将打印整个缓冲区:不管您刚才读取了多少,加上缓冲区末尾剩余的1000字节。在现实生活中,您可能希望对此做些什么(可能是结果或缓冲区的位置)completed
方法中找出buffer
这是一个类变量,但是channel
这也是一个类变量,它是空的。我还没有弄清楚为什么会是空的。所以我更改了它,使它将channel
作为附件而不是缓冲区传递。仍然没有我觉得很有道理read
。按Enter
退出pos
维护您正在读取的文件中的位置complete
方法中启动另一个异步读取时,神奇的事情就发生了。这就是为什么我放弃了匿名类并实现了接口本身 Path file = Paths.get("c:/large.log");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
final ByteBuffer buffer = ByteBuffer.allocate(1000);
channel.read(buffer, 0, buffer,
new CompletionHandler<Integer, ByteBuffer>() {
public void completed(Integer result, ByteBuffer attachment) {
System.out.println(new String(buffer.array()));
}
});
import java.nio.*;
导入java.nio.channels.*;
导入java.nio.file.*;
导入java.io.IOException;
公共类TryNio实现CompletionHandler{
//需要跟踪下一个位置。
int pos=0;
AsynchronousFileChannel通道=空;
ByteBuffer缓冲区=null;
公共无效已完成(整数结果,异步文件通道附件){
//若结果为-1,则表示未读取任何内容。
如果(结果!=-1){
pos+=result;//不要再读取相同的文本。
//您的输出命令。
System.out.println(新字符串(buffer.array());
buffer.clear();//重置缓冲区,以便阅读更多内容。
}
//使用此命令启动另一个异步读取。
附件。读取(缓冲区、pos、附件、本);
}
公共作废失败(可丢弃的exc,
异步文件通道(附件){
System.err.println(“错误!”);
exc.printStackTrace();
}
公共无效doit(){
Path file=Path.get(“/var/log/syslog”);
AsynchronousFileChannel通道=空;
试一试{
channel=AsynchronousFileChannel.open(文件);
}捕获(IOE异常){
System.err.println(“无法打开文件:+file.toString());
系统。出口(1);//是的,呵呵。
}
缓冲区=字节缓冲区分配(1000);
//启动异步读取。
通道读取(缓冲器、pos、通道、本机);
//这个方法现在退出,线程返回main并等待用户输入。
}
公共静态void main(字符串[]args){
TryNio tn=新TryNio();
tn.doit();
//等待fur用户按键,否则java将退出,因为
//异步线程不够重要,无法保持其运行。
请尝试{System.in.read();}捕获(IOE异常){}
}
}
使用文件中的位置和文件大小,需要在completionhandler中重复调用异步读取操作以读取整个文件。每次读取操作完成时,需要使用红色字节数增加位置
下面是completionhandler异步读取整个文件的完整方法。有关完整示例,请参阅
GregHNZ解决方案非常好,因为我必须在不同的项目中多次使用此类代码,所以我最终将其放入了一个辅助库
RxIo
,我在Maven Central Repository中发布了该库,github Repository中也提供了该库。使用该工具,您可以读取文件的所有字节,如:
public void completed(Integer result, ByteBuffer attachment) {
try {
bb.flip();
System.out.println("bytea red "+bb.limit());
if(afc.size() > position) {
position = position + bb.limit();
bb.clear();
//pass the same completion handler
afc.read(bb, position, bb, this);
}
} catch (IOException e) {
e.printStackTrace();
}
}
分配默认大小为262144的ByteBuffer
,但您可以使用readAllBytes(路径文件,int-bufferSize)
指定不同的值
您可以在中看到其他用例。对我有效。当然,您必须清除缓冲区,并在读取中增加position参数,因此最终变量有点混乱,但这是可以做到的。我已经执行了此示例代码。Bu
public void completed(Integer result, ByteBuffer attachment) {
try {
bb.flip();
System.out.println("bytea red "+bb.limit());
if(afc.size() > position) {
position = position + bb.limit();
bb.clear();
//pass the same completion handler
afc.read(bb, position, bb, this);
}
} catch (IOException e) {
e.printStackTrace();
}
}
AsyncFiles
.readAllBytes(Paths.get("input.txt"))
.thenApply(bytes -> { /*... use bytes... */});