2012-07-11 16 views
6

Estoy usando la biblioteca Apache Commons 1.4.1 para comprimir y descomprimir archivos ".tar.gz".Cómo descomprimir un archivo TAR utilizando Apache Commons

Estoy teniendo problemas con el último bit - la conversión de un TarArchiveInputStream en un FileOutputStream.

Por extraño que parezca, es romper en esta línea:

FileOutputStream fout = new FileOutputStream(destPath); 

destPath es un archivo con una ruta canónica de: C: \ Documents and Settings \ Administrador \ Mis documentos \ JavaWorkspace \ BackupUtility \ untarred \ Test \ subdirectorio \ testinsub.txt

error producido:

Exception in thread "main" java.io.IOException: The system cannot find the path specified 

¿Alguna idea de lo que podría ser? ¿Y por qué no puede encontrar el camino?

Estoy adjuntando todo el método a continuación (la mayoría de los cuales se elimina de here).

private void untar(File dest) throws IOException { 
    dest.mkdir(); 
    TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); 
    // tarIn is a TarArchiveInputStream 
    while (tarEntry != null) {// create a file with the same name as the tarEntry 
     File destPath = new File(dest.toString() + System.getProperty("file.separator") + tarEntry.getName()); 
     System.out.println("working: " + destPath.getCanonicalPath()); 
     if (tarEntry.isDirectory()) { 
      destPath.mkdirs(); 
     } else { 
      destPath.createNewFile(); 
      FileOutputStream fout = new FileOutputStream(destPath); 
      tarIn.read(new byte[(int) tarEntry.getSize()]); 
      fout.close(); 
     } 
     tarEntry = tarIn.getNextTarEntry(); 
    } 
    tarIn.close(); 
} 
+0

Estoy avergonzado de preguntar esto, pero traté de usar tu código de muestra y lo vi funcionar dado un archivo 'gzip' en particular con el que estaba trabajando. ¿Cómo funciona esto sin llamar a 'fout.write (...)' dado el contenido leído en InputStream? En [answer @ user1894600 suggestions] (http://stackoverflow.com/a/14211580/320399), tiene que llamar explícitamente a 'write (...)' y proporcionar la matriz de bytes que se ha leído en la memoria. – blong

Respuesta

5

Un par de puntos generales, ¿por qué lo hace vudú con la File constructor, donde hay una perfectly usable constructor donde se puede definir el nombre de la File desea crear y dar un archivo principal?

En segundo lugar, no estoy muy seguro de cómo se manejan los espacios vacíos en las rutas de las ventanas. Puede ser la causa de tus problemas. Tratar de usar el constructor he mencionado anteriormente y ver si se hace una diferencia:. File destPath = new File(dest, tarEntry.getName()); (suponiendo que File dest es un archivo adecuado, y existe y es accesible por usted

En tercer lugar, antes de hacer nada con un objeto File debe comprobar si existe y si es accesible. Eso será en última instancia, ayudará a identificar el problema.

+0

Gracias por su respuesta. Decidí reescribir el módulo y funciona muy bien. He seguido tu consejo sobre no jugar con el objeto File, así que voy a marcar tu respuesta como la correcta (según el principio) – Redandwhite

+0

Me alegro de que haya sido de ayuda, y espero que todo salga bien al final. Buena suerte :) – posdef

+0

Estoy usando el mismo código para descomprimir un archivo .tar que .tar.gz. Y obtengo de esta línea 'nuevo archivo (dest, tarEntry.getName())' el contenido del archivo y no el nombre del archivo. ¿Qué puedo hacer para obtener el nombre de archivo dentro de .tar –

13

Su programa tiene el error java espacio de almacenamiento dinámico. así que creo que un pequeño cambio necesario. aquí es el código ...

public static void uncompressTarGZ(File tarFile, File dest) throws IOException { 
    dest.mkdir(); 
    TarArchiveInputStream tarIn = null; 

    tarIn = new TarArchiveInputStream(
       new GzipCompressorInputStream(
        new BufferedInputStream(
         new FileInputStream(
          tarFile 
         ) 
        ) 
       ) 
      ); 

    TarArchiveEntry tarEntry = tarIn.getNextTarEntry(); 
    // tarIn is a TarArchiveInputStream 
    while (tarEntry != null) {// create a file with the same name as the tarEntry 
     File destPath = new File(dest, tarEntry.getName()); 
     System.out.println("working: " + destPath.getCanonicalPath()); 
     if (tarEntry.isDirectory()) { 
      destPath.mkdirs(); 
     } else { 
      destPath.createNewFile(); 
      //byte [] btoRead = new byte[(int)tarEntry.getSize()]; 
      byte [] btoRead = new byte[1024]; 
      //FileInputStream fin 
      // = new FileInputStream(destPath.getCanonicalPath()); 
      BufferedOutputStream bout = 
       new BufferedOutputStream(new FileOutputStream(destPath)); 
      int len = 0; 

      while((len = tarIn.read(btoRead)) != -1) 
      { 
       bout.write(btoRead,0,len); 
      } 

      bout.close(); 
      btoRead = null; 

     } 
     tarEntry = tarIn.getNextTarEntry(); 
    } 
    tarIn.close(); 
} 

bueno l uck

+0

? Entonces, el error de espacio de montón ocurriría porque la matriz de bytes es potencialmente demasiado grande cuando se declara como 'byte [] btoRead = new byte [(int) tarEntry.getSize() ]; '? – blong

+1

Excelente respuesta. Sin embargo, el siguiente 'deskPath.createNewFile();' debe modificarse para crear el directorio padre 'if (! DestPath.getParentFile().exists()) { destPath.getParentFile(). mkdirs(); } destPath.createNewFile(); ' –

Cuestiones relacionadas