使用Java NIO读取和写入大文件

时间:2016-12-13 07:43:20

标签: java nio file-processing

如何使用Java NIO框架有效地从大文件中读取并将批量数据写入文件。

我正在使用ByteBufferFileChannel并尝试过以下内容:

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,我应该遵循相同的程序吗?

如果书面操作是批量编写的话,我在编写时想要做的类似事情应该遵循什么?

2 个答案:

答案 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 directlyFileInputStream / 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,我应该遵循相同的程序吗?

是。文件大小没有任何区别。