Pergunta

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

Foi útil?

Solução

Nota: Esta funcionalidade foi publicado mais tarde através de um projeto separado, Apache Commons Compress, como descrito em outro resposta. Esta resposta está fora de data.


Eu não usei um tar API diretamente, mas alcatrão e bzip2 são implementados em Ant; você poderia pedir a sua execução, ou, eventualmente, usar Ant para fazer o que você precisa.

Gzip faz parte de Java SE (e eu estou supondo que a implementação 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 forma que você usaria qualquer InputStream:

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

(Note que o GZIPInputStream tem seu próprio buffer, interna, de modo envolvendo a FileInputStream em um BufferedInputStream provavelmente diminuir o desempenho.)

Outras dicas

Você pode fazer isso com a biblioteca Apache Commons Compress. Você pode baixar a versão 1.2 de http://mvnrepository.com/artifact/ org.apache.commons / comuns-compressa / 1,2 .

Aqui estão dois métodos: um que descompacta um arquivo e um outro que untars-lo. Assim, para um arquivo tar.gz, você precisa primeiro descompactá-lo e depois que descompacte-o. Por favor, note que o arquivo tar pode conter pastas, bem como, caso em que eles precisam ser criado no sistema de arquivos local.

Aproveite.

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

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

TrueZip ou seu sucessor TrueVFS faz o mesmo ... também é disponível a partir Maven Central.

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

Dependência:

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

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

Aqui está um exemplo com 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 Maven:

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

Além de gzip e bzip2, Apache Commons Compress API também tem suporte alcatrão, originalmente baseada em ICE Engenharia Java Tar Package, que é tanto ferramenta API e independente.

Que tal usar este API para arquivos tar, este outro incluído dentro Ant para BZIP2 e um padrão para GZIP?

Aqui está uma versão com base em esta resposta anteriormente por Dan Borza que usos Apache Commons Compress e Java NIO (ie caminho em vez de Arquivo). Ele também faz a descompactação e untarring em um fluxo por isso não há criação de arquivo intermediário.

public static void unTarGz( Path pathInput, Path pathOutput ) throws IOException {
    TarArchiveInputStream tararchiveinputstream =
        new TarArchiveInputStream(
            new GzipCompressorInputStream(
                new BufferedInputStream( Files.newInputStream( pathInput ) ) ) );

    ArchiveEntry archiveentry = null;
    while( (archiveentry = tararchiveinputstream.getNextEntry()) != null ) {
        Path pathEntryOutput = pathOutput.resolve( archiveentry.getName() );
        if( archiveentry.isDirectory() ) {
            if( !Files.exists( pathEntryOutput ) )
                Files.createDirectory( pathEntryOutput );
        }
        else
            Files.copy( tararchiveinputstream, pathEntryOutput );
    }

    tararchiveinputstream.close();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top