2016-12-13 44 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