增量读取大文件的最快方法

给定MAX_BUFFER_SIZE的缓冲区,并且文件远远超过它时,如何:

  1. 以MAX_BUFFER_SIZE块的forms读取文件?
  2. 尽可能快地完成

我尝试使用NIO

RandomAccessFile aFile = new RandomAccessFile(fileName, "r"); FileChannel inChannel = aFile.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(CAPARICY); int bytesRead = inChannel.read(buffer); buffer.flip(); while (buffer.hasRemaining()) { buffer.get(); } buffer.clear(); bytesRead = inChannel.read(buffer); aFile.close(); 

和常规IO

  InputStream in = new FileInputStream(fileName); long length = fileName.length(); if (length > Integer.MAX_VALUE) { throw new IOException("File is too large!"); } byte[] bytes = new byte[(int) length]; int offset = 0; int numRead = 0; while (offset = 0) { offset += numRead; } if (offset < bytes.length) { throw new IOException("Could not completely read file " + fileName); } in.close(); 

事实certificate, 与NIO做同样的事情常规IO的速度要快100倍 。 我错过了什么吗? 这是预期的吗? 有没有更快的方法来读取缓冲区块中的文件?

最终,我正在处理一个大文件,我没有记忆,可以一次性阅读。 相反,我想以块的forms逐步读取它,然后用于处理。

假设您需要立即将整个文件读入内存(正如您当前所做的那样),读取较小的块或NIO都不会帮助您。

实际上,您可能最好阅读更大的块 – 您的常规IO代码会自动为您执行此操作。

您的NIO代码目前较慢,因为您一次只读取一个字节(使用buffer.get(); )。

如果你想以块的forms处理 – 例如,在流之间进行传输 – 这是在没有NIO的情况下执行它的标准方法:

 InputStream is = ...; OutputStream os = ...; byte buffer[] = new byte[1024]; int read; while((read = is.read(buffer)) != -1){ os.write(buffer, 0, read); } 

这使用的缓冲区大小仅为1 KB,但可以传输无限量的数据。

(如果你扩展你的答案,详细说明你在function层面上的实际目的,我可以进一步改进这个以获得更好的答案。)

如果你想让你的第一个例子更快

 FileChannel inChannel = new FileInputStream(fileName).getChannel(); ByteBuffer buffer = ByteBuffer.allocateDirect(CAPACITY); while(inChannel.read(buffer) > 0) buffer.clear(); // do something with the data and clear/compact it. inChannel.close(); 

如果你想要它更快。

 FileChannel inChannel = new RandomAccessFile(fileName, "r").getChannel(); MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); // access the buffer as you wish. inChannel.close(); 

对于最大2 GB的文件,这可能需要10 – 20微秒。