2016-12-13 41 views
0

如何从大文件中有效读取数据并使用Java NIO框架将批量数据写入文件中。使用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我的文件的大小?

如果书写操作是批量书写时我想要做的类似的事情,我该怎么办?

+0

FileInputStream/FileOutputStream绕道你们是不是来处理的数据,或者你只是想复制呢? – Kayaman

+1

'如果我想要做类似的事情'是什么意思? – EJP

回答

1

请注意,您可以简单地使用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端缓冲区。如果这不能解决您的需求,您必须在您的问题中更具体。

顺便说一句,你可以不open a FileChannel directly自从Java 7

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?

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

+0

如果文件大小很大,此更改将如何产生影响? – KayV

+0

它将确保不完整的写入不会丢失,并且最终的读取内容会被刷新。此代码适用于从零开始的任何文件大小。 – EJP