如何使用Java NIO
框架有效地从大文件中读取并将批量数据写入文件。
我正在使用ByteBuffer
和FileChannel
并尝试过以下内容:
public static void main(String[] args)
{
String inFileStr = "screen.png";
String outFileStr = "screen-out.png";
long startTime, elapsedTime;
int bufferSizeKB = 4;
int bufferSize = bufferSizeKB * 1024;
// Check file length
File fileIn = new File(inFileStr);
System.out.println("File size is " + fileIn.length() + " bytes");
System.out.println("Buffer size is " + bufferSizeKB + " KB");
System.out.println("Using FileChannel with an indirect ByteBuffer of " + bufferSizeKB + " KB");
try ( FileChannel in = new FileInputStream(inFileStr).getChannel();
FileChannel out = new FileOutputStream(outFileStr).getChannel() )
{
// Allocate an indirect ByteBuffer
ByteBuffer bytebuf = ByteBuffer.allocate(bufferSize);
startTime = System.nanoTime();
int bytesCount = 0;
// Read data from file into ByteBuffer
while ((bytesCount = in.read(bytebuf)) > 0) {
// flip the buffer which set the limit to current position, and position to 0.
bytebuf.flip();
out.write(bytebuf); // Write data from ByteBuffer to file
bytebuf.clear(); // For the next read
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed Time is " + (elapsedTime / 1000000.0) + " msec");
}
catch (IOException ex) {
ex.printStackTrace();
}
}
任何人都可以告诉我,如果我的文件大小超过2 GB,我应该遵循相同的程序吗?
如果书面操作是批量编写的话,我在编写时想要做的类似事情应该遵循什么?
答案 0 :(得分:2)
请注意,您只需使用Files.copy(Paths.get(inFileStr),Paths.get(outFileStr), StandardCopyOption.REPLACE_EXISTING)
复制文件,就像您的示例代码一样,只需更快,只需一行代码。
否则,如果您已经打开了两个文件通道,则可以使用
in.transferTo(0, in.size(), out)
将in
频道的全部内容转移到out
频道。请注意,此方法允许指定源文件中将转移到目标通道的当前位置(最初为零)的范围,并且还有一种相反方式的方法,即out.transferFrom(in, 0, in.size())
从中传输数据源通道的当前位置到目标文件中的绝对范围。
它们一起允许几乎所有可以想象的非平凡的批量传输,而无需将数据复制到Java端缓冲区。如果这不能解决您的需求,您必须在问题中更具体。
顺便说一下,自Java 7以来,您可以open a FileChannel
directly绕FileInputStream
/ FileOutputStream
绕道而行。
答案 1 :(得分:0)
while ((bytesCount = in.read(bytebuf)) > 0) {
// flip the buffer which set the limit to current position, and position to 0.
bytebuf.flip();
out.write(bytebuf); // Write data from ByteBuffer to file
bytebuf.clear(); // For the next read
}
您的复制循环不正确。它应该是:
while ((bytesCount = in.read(bytebuf)) > 0 || bytebuf.position() > 0) {
// flip the buffer which set the limit to current position, and position to 0.
bytebuf.flip();
out.write(bytebuf); // Write data from ByteBuffer to file
bytebuf.compact(); // For the next read
}
任何人都可以告诉我,如果我的文件大小超过2 GB,我应该遵循相同的程序吗?
是。文件大小没有任何区别。