Como faço para extrair um arquivo tar em Java?

Como faço para extrair um arquivo tar (ou tar.gz, ou tar.bz2) em Java?

Nota: Esta funcionalidade foi posteriormente publicada através de um projeto separado, o Apache Commons Compress, conforme descrito em outra resposta. Esta resposta está desatualizada.


Eu não usei uma API tar diretamente, mas tar e bzip2 são implementados no Ant; você poderia emprestar sua implementação, ou possivelmente usar Ant para fazer o que você precisa.

O gzip faz parte do Java SE (e estou supondo que a implementação do Ant segue o mesmo modelo).

GZIPInputStream é apenas um decorador InputStream . Você pode envolver, por exemplo, um FileInputStream em um GZIPInputStream e usá-lo da mesma maneira que você usaria qualquer InputStream :

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

(Observe que o GZIPInputStream tem seu próprio buffer interno, portanto, agrupar o FileInputStream em um BufferedInputStream provavelmente diminuiria o desempenho.)

Você pode fazer isso com a biblioteca Apache Commons Compress. Você pode baixar a versão 1.2 em http://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.2 .

Aqui estão dois methods: um que descompacta um arquivo e outro que o desativa. Portanto, para um arquivo tar.gz, primeiro é necessário descompactá-lo e depois descompactá-lo. Por favor, note que o arquivo tar também pode conter pastas, caso elas precisem ser criadas no sistema de arquivos local.

Apreciar.

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

O Apache Commons VFS suporta tar como um sistema de arquivos virtual , que suporta URLs como esta tar:gz: http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt

TrueZip ou seu sucessor O TrueVFS faz o mesmo … ele também está disponível no Maven Central.

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

Dependência:

   org.rauschig jarchivelib 0.5.0  

Eu tentei um monte de libs sugeridas (TrueZip, Apache Compress), mas sem sorte.

Aqui está um exemplo com o 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(); } } 

E a dependência do maven:

   commons-vfs commons-vfs 1.0  

Além do gzip e do bzip2, o Apache Commons Compress API também tem suporte ao tar, originalmente baseado no Pacote de Tar de Java da ICE Engineering , que é tanto uma API quanto uma ferramenta autônoma.

Que tal usar esta API para arquivos tar, esta outra incluída dentro do Ant para BZIP2 e a padrão para o GZIP?