2017-05-19 3 views
0

Verwendung Ich habe folgenden Code implementieren Datei (Binär-Datei) Codejava: beschädigte Zip-Datei erstellt, wenn Kopie nio

private void copyFileWithChannels(File aSourceFile, File aTargetFile) { 
     log("Copying files with channels.");   
     FileChannel inChannel = null; 
     FileChannel outChannel = null; 
     FileInputStream inStream = null; 
     FileOutputStream outStream = null;  
     try { 
      inStream = new FileInputStream(aSourceFile); 
      inChannel = inStream.getChannel(); 
      outStream = new FileOutputStream(aTargetFile);   
      outChannel = outStream.getChannel(); 
      long bytesTransferred = 0; 
      while(bytesTransferred < inChannel.size()){ 
       bytesTransferred += inChannel.transferTo(0, inChannel.size(), outChannel); 
      } 
     } 
     catch(FileNotFoundException e){ 
      log.error("FileNotFoundException in copyFileWithChannels()",e); 
     } 
     catch (IOException e) { 
      log.error("IOException in copyFileWithChannels()",e);   
     } 
     catch (Exception e) { 
      log.error("Exception in copyFileWithChannels()",e); 
     } 
     finally { 
      try{ 
       if (inChannel != null) inChannel.close(); 
       if (outChannel != null) outChannel.close(); 
       if (inStream != null) inStream.close(); 
       if (outStream != null) outStream.close(); 
      }catch(Exception e){ 
       log.error("Exception in copyFileWithChannels() while closing the stream",e); 
      } 
     } 

    } 

Ich habe Testcode mit einer ZIP-Datei zu kopieren. Wenn ich die Datei verifiziere, habe ich festgestellt, dass die erzeugte Datei beschädigt ist (die Größe wurde erhöht). Quell-Zip-Datei ist etwa 9 GB.

Antwort

1

Die transferTo Methode das erste Argument gibt die verweist Position von welcher zu tra nsfer, nicht relativ zum Speicherort des Streams, sondern relativ zum Anfang der Datei. Da Sie 0 dort eingeben, wird es immer vom Anfang der Datei übertragen. So daß die Leitung

bytesTransferred += inChannel.transferTo(bytesTransferred , inChannel.size(), outChannel); 

mavarazy in seiner Antwort erwähnt werden muss ist er nicht sicher, ob Sie eine Schleife benötigen, wenn inChannel.size() verwenden, da die Erwartung, dass, wenn Sie die ganze Größe liefern wird die gesamte Datei kopieren. Die tatsächliche Übertragung kann jedoch geringer sein als die angeforderte Anzahl von Bytes, wenn der Puffer des Ausgabekanals weniger Platz zur Verfügung hat. Sie brauchen also die Schleife wie in seinem zweiten Code-Snippet.

+0

Ich habe meine Antwort korrigiert, danke – mavarazy

0

Sofern Sie keinen guten Grund haben, Files.copy(Path, Path, CopyOption...) zu verwenden.

+0

Files.copy verwendet Kopie mit Lese-/Schreibmechanismus, den ich bereits implementiert habe, in dem ich Leistungsproblem habe. – mcacorner