¿Cómo extraigo un archivo tar en Java?

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

    Nota: Esta funcionalidad se publicó posteriormente a través de un proyecto separado, Apache Commons Compress, como se describe en otra respuesta. 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 es parte de Java SE (y supongo que la implementación Ant sigue el mismo modelo).

    GZIPInputStream es solo un decorador InputStream . Puede envolver, por ejemplo, un FileInputStream en un GZIPInputStream y usarlo de la misma manera que usaría cualquier InputStream :

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

    (Tenga en cuenta que GZIPInputStream tiene su propio búfer interno, por lo que FileInputStream en un BufferedInputStream probablemente disminuirá el rendimiento).

    Puede hacer esto con la biblioteca Apache Commons Compress. 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 anota. Entonces, para un archivo 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.

    Disfrutar.

     /** 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 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 untaredFiles = new LinkedList(); 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. * 

    * 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; }

    Apache Commons VFS admite tar como un sistema de archivos virtual , que admite URLs como esta tar:gz: http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt

    TrueZip o su sucesor TrueVFS hace lo mismo … también está disponible desde Maven Central.

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

    Dependencia:

       org.rauschig jarchivelib 0.5.0  

    Simplemente probé algunas de las librerías sugeridas (TrueZip, Apache Compress), pero no tuve suerte.

    Aquí hay 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:

       commons-vfs commons-vfs 1.0  

    Además de gzip y bzip2, Apache Commons Compress API también tiene soporte tar, originalmente basado en ICE Engineering Java Tar Package , que es tanto una API como una herramienta independiente.

    ¿Qué pasa con el uso de esta API para archivos tar, este otro incluido dentro de Ant para BZIP2 y el estándar para GZIP?