2017-05-19 2 views
0

j'implémenter le code ci-dessous pour copier le fichier (fichier binaire) Codejava: fichier zip corrompu créé lors de copie à l'aide 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); 
      } 
     } 

    } 

J'ai le code de test avec un fichier zip. Quand je vérifie le fichier, j'ai trouvé que le fichier généré est corrompu (la taille a été augmentée). Le fichier zip source est d'environ 9 Go.

Répondre

1

premier argument de la méthode transferTo donne la position à partir de laquelle tra nsfer, non par rapport à l'endroit où le flux s'est arrêté, mais par rapport au début du fichier. Puisque vous y mettez 0, il sera toujours transféré depuis le début du fichier. Ainsi, cette ligne doit être

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

mavarazy mentionné dans sa réponse, il est pas sûr si vous avez besoin d'une boucle lors de l'utilisation inChannel.size(), car l'attente est que si vous fournissez la taille entière, il copie le fichier entier. Cependant, le transfert réel peut être inférieur au nombre d'octets demandé si le tampon du canal de sortie a moins de place disponible. Vous avez donc besoin de la boucle comme dans son second extrait de code.

+0

J'ai corrigé ma réponse, merci – mavarazy

0

Sauf si vous avez une bonne raison d'utiliser Files.copy(Path, Path, CopyOption...).

+0

Files.copy utilise la copie en utilisant le mécanisme de lecture/écriture que j'ai déjà implémenté, dans lequel j'ai un problème de performance. – mcacorner