2016-12-13 12 views
0

Wie kann ich effektiv aus einer großen Datei lesen und Massendaten in eine Datei schreiben mit dem Java NIO Framework.Lesen und Schreiben einer großen Datei mit Java NIO

Ich arbeite mit ByteBuffer und FileChannel und hatte sich wie unten etwas versucht:

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(); 
    } 
} 

Kann jemand sagen, ich sollte das gleiche Verfahren, wenn meine Dateigröße in mehr als 2 GB folgen?

Was sollte ich tun, wenn die gleichen Dinge, die ich beim Schreiben tun möchte, wenn geschriebene Operationen in großen Mengen sind?

+0

Sind Sie versuchen, die Daten zwischendurch, oder wollen Sie einfach nur kopieren zu verarbeiten? – Kayaman

+1

Was bedeutet "wenn die gleichen Dinge, die ich machen möchte"? – EJP

Antwort

1

Beachten Sie, dass Sie einfach Files.copy(Paths.get(inFileStr),Paths.get(outFileStr), StandardCopyOption.REPLACE_EXISTING) verwenden können, um die Datei zu kopieren, wie es Ihr Beispielcode tut, nur wahrscheinlich schneller und mit nur einer Codezeile.

Andernfalls, wenn Sie bereits die beiden Datei Kanäle geöffnet haben, können Sie einfach
in.transferTo(0, in.size(), out) verwenden Sie den gesamten Inhalt des in Kanal auf den out Kanal zu übertragen. Beachten Sie, dass mit dieser Methode ein Bereich innerhalb der Quelldatei angegeben werden kann, der an die aktuelle Position des Zielkanals übertragen wird (der anfänglich Null ist). Außerdem gibt es eine Methode für den umgekehrten Weg, dh out.transferFrom(in, 0, in.size()), um Daten aus dem aktuellen Quellkanal zu übertragen Position zu einem absoluten Bereich innerhalb der Zieldatei.

Zusammen erlauben sie fast jede erdenkliche nichttriviale Massenübertragung auf effiziente Weise, ohne dass die Daten in einen Java-Seitenpuffer kopiert werden müssen. Wenn das Ihre Bedürfnisse nicht löst, müssen Sie in Ihrer Frage spezifischer sein.

By the way, können Sie open a FileChannel directly ohne FileInputStream/FileOutputStream Umweg seit 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 
    } 

Ihre Kopierschleife ist nicht korrekt. Es sollte sein:

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 
    } 

jemand sagen kann, sollte ich nach dem gleichen Verfahren, wenn meine Dateigröße mehr als 2 GB [ist]?

Ja. Die Dateigröße macht keinen Unterschied.

+0

Wie wirkt sich diese Änderung aus, wenn die Dateigröße groß ist? – KayV

+0

Es wird sichergestellt, dass unvollständige Schreibvorgänge nicht verloren gehen und dass das letzte Stück gelesen wird. Dieser Code funktioniert für jede Dateigröße von Null aufwärts. – EJP