2008-11-24 30 views
54

¿Cómo extraigo un archivo tar (o tar.gz, o tar.bz2) en Java?¿Cómo extraigo un archivo tar en Java?

+0

skiphoppy, después de 2008, cuando originalmente respondí, el proyecto Apache Commons Comprimir fue puesto en libertad. Probablemente deberías aceptar [esta respuesta] (http://stackoverflow.com/a/7556307/3474) para que se destaque más. – erickson

Respuesta

17

Nota: Esta funcionalidad se publicó posteriormente a través de un proyecto independiente, Apache Commons Compress, como described in another answer. Esta respuesta no está actualizada.


No he usado una API tar directamente, pero tar y bzip2 están implementados en Ant; podría tomar prestada su implementación, o posiblemente usar Ant para hacer lo que necesita.

Gzip is part of Java SE (y supongo que la implementación de Ant sigue el mismo modelo).

GZIPInputStream es solo un decorador InputStream. Usted puede envolver, por ejemplo, un FileInputStream en un GZIPInputStream y utilizarlo de la misma manera que tendría que utilizar cualquier InputStream:

InputStream is = new GZIPInputStream(new FileInputStream(file)); 

(Tenga en cuenta que la GZIPInputStream tiene su propio buffer, interno, por lo que envuelve el FileInputStream en un BufferedInputStream probablemente disminuirá el rendimiento.)

+2

estaba a punto de contarle sobre GZIPInputStream. Pero no lo ayudará, ya que todavía necesita leer el archivo .tar contenido :) –

+1

La verdad es que ya sé sobre GZIPInputStream, gracias a otra pregunta que hice aquí. Pero no sé nada acerca de las API tar, y esperaba que pudiera haber algo que manejara gzip de manera integrada, así que no quería limitar las respuestas diciendo todo lo que ya sabía. – skiphoppy

+3

Las clases de Apache incluidas en 'ant' funcionan bien. Lo uso todos los días: org.apache.tools.tar.TarEntry y org.apache.tools.tar.TarInputStream; el código es muy similar al que usarías para descomprimir archivos zip. Si quieres hacer Bzip2, usa jaxlib. – tucuxi

4

¿Qué hay de usar este API para archivos tar, este other one incluido dentro de Ant para BZIP2 y el standard one para GZIP?

5

Además de gzip y bzip2, Apache Commons Compress API tiene también el apoyo de alquitrán, originalmente basado en ICE Engineering Java Tar Package, que es a la vez activos y de herramienta independiente.

+1

Apache Commons Compress API tiene soporte de alquitrán y se basa originalmente en el paquete ICE tar anterior Creo: http://commons.apache.org/compress/ –

+2

Mi prueba muestra ICE tar para ser el más rápido entre los cinco contendientes (hielo, comprimir, hormiga , xeus + vfs), mientras que Commons Compress ocupa el segundo lugar ... sin embargo, ICE tar parece un poco menos completo de WRT al desempaquetar todas las entradas y WRT mantiene las entradas de archivo originales. –

6

Acabo de probar algunas de las librerías sugeridas (TrueZip, Apache Compress), pero no tuve suerte.

Aquí se muestra un ejemplo con Apache Commons VFS:

FileSystemManager fsManager = VFS.getManager(); 
FileObject archive = fsManager.resolveFile("tgz:file://" + fileName); 

// List the children of the archive file 
FileObject[] children = archive.getChildren(); 
System.out.println("Children of " + archive.getName().getURI()+" are "); 
for (int i = 0; i < children.length; i++) { 
    FileObject fo = children[i]; 
    System.out.println(fo.getName().getBaseName()); 
    if (fo.isReadable() && fo.getType() == FileType.FILE 
     && fo.getName().getExtension().equals("nxml")) { 
     FileContent fc = fo.getContent(); 
     InputStream is = fc.getInputStream(); 
    } 
} 

Y la dependencia Maven:

<dependency> 
     <groupId>commons-vfs</groupId> 
     <artifactId>commons-vfs</artifactId> 
     <version>1.0</version> 
    </dependency> 
58

Usted puede hacer esto con la biblioteca Apache Commons Comprimir. Puede descargar la versión 1.2 desde http://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.2.

Aquí hay dos métodos: uno que descomprime un archivo y otro que lo recupera. Por lo tanto, para un archivo <fileName> tar.gz, primero debe descomprimirlo y luego desmarcarlo. Tenga en cuenta que el archivo tar también puede contener carpetas, caso en que deben crearse en el sistema de archivos local.

Disfrútalo.

/** Untar an input file into an output file. 

* The output file is created in the output folder, having the same name 
* as the input file, minus the '.tar' extension. 
* 
* @param inputFile  the input .tar file 
* @param outputDir  the output directory file. 
* @throws IOException 
* @throws FileNotFoundException 
* 
* @return The {@link List} of {@link File}s with the untared content. 
* @throws ArchiveException 
*/ 
private static List<File> unTar(final File inputFile, final File outputDir) throws FileNotFoundException, IOException, ArchiveException { 

    LOG.info(String.format("Untaring %s to dir %s.", inputFile.getAbsolutePath(), outputDir.getAbsolutePath())); 

    final List<File> untaredFiles = new LinkedList<File>(); 
    final InputStream is = new FileInputStream(inputFile); 
    final TarArchiveInputStream debInputStream = (TarArchiveInputStream) new ArchiveStreamFactory().createArchiveInputStream("tar", is); 
    TarArchiveEntry entry = null; 
    while ((entry = (TarArchiveEntry)debInputStream.getNextEntry()) != null) { 
     final File outputFile = new File(outputDir, entry.getName()); 
     if (entry.isDirectory()) { 
      LOG.info(String.format("Attempting to write output directory %s.", outputFile.getAbsolutePath())); 
      if (!outputFile.exists()) { 
       LOG.info(String.format("Attempting to create output directory %s.", outputFile.getAbsolutePath())); 
       if (!outputFile.mkdirs()) { 
        throw new IllegalStateException(String.format("Couldn't create directory %s.", outputFile.getAbsolutePath())); 
       } 
      } 
     } else { 
      LOG.info(String.format("Creating output file %s.", outputFile.getAbsolutePath())); 
      final OutputStream outputFileStream = new FileOutputStream(outputFile); 
      IOUtils.copy(debInputStream, outputFileStream); 
      outputFileStream.close(); 
     } 
     untaredFiles.add(outputFile); 
    } 
    debInputStream.close(); 

    return untaredFiles; 
} 

/** 
* Ungzip an input file into an output file. 
* <p> 
* The output file is created in the output folder, having the same name 
* as the input file, minus the '.gz' extension. 
* 
* @param inputFile  the input .gz file 
* @param outputDir  the output directory file. 
* @throws IOException 
* @throws FileNotFoundException 
* 
* @return The {@File} with the ungzipped content. 
*/ 
private static File unGzip(final File inputFile, final File outputDir) throws FileNotFoundException, IOException { 

    LOG.info(String.format("Ungzipping %s to dir %s.", inputFile.getAbsolutePath(), outputDir.getAbsolutePath())); 

    final File outputFile = new File(outputDir, inputFile.getName().substring(0, inputFile.getName().length() - 3)); 

    final GZIPInputStream in = new GZIPInputStream(new FileInputStream(inputFile)); 
    final FileOutputStream out = new FileOutputStream(outputFile); 

    IOUtils.copy(in, out); 

    in.close(); 
    out.close(); 

    return outputFile; 
} 
+0

Su ejemplo es un gran comienzo, pero parece que tengo un problema con: while ((entry = (TarArchiveEntry) debInputStream.getNextEntry())! = Null). el problema es cuando proceso el primer archivo a través de framewokr externo (por ej. SAXBuilder), la corriente de entrada debInputStream se cierra y la segunda llamada de depInputStream.getNextEntry() arroja una excepción "buffer de entrada cerrado" – adranale

+0

Relacionado, con una implementación similar : [Cómo desbloquear un archivo TAR utilizando Apache Commons] (http://stackoverflow.com/a/14211580/320399) – blong

+0

Gracias por compartir. Hubiera sido bueno si pusieran un método unTar en la biblioteca de compresas apache. Parece una operación fundamental. – Andrew

9
Archiver archiver = ArchiverFactory.createArchiver("tar", "gz"); 
archiver.extract(archiveFile, destDir); 

Dependencia:

<dependency> 
     <groupId>org.rauschig</groupId> 
     <artifactId>jarchivelib</artifactId> 
     <version>0.5.0</version> 
</dependency> 
Cuestiones relacionadas