如何在 Java 中提取 tar 文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/315618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:04:04  来源:igfitidea点击:

How do I extract a tar file in Java?

javaarchivetar

提问by skiphoppy

How do I extract a tar (or tar.gz, or tar.bz2) file in Java?

如何在 Java 中提取 tar(或 tar.gz 或 tar.bz2)文件?

采纳答案by erickson

Note:This functionality was later published through a separate project, Apache Commons Compress, as described in another answer.This answer is out of date.

注意:此功能后来通过一个单独的项目 Apache Commons Compress 发布,如另一个答案中所述。这个答案已经过时了。



I haven't used a tar API directly, but tar and bzip2 are implemented in Ant; you could borrow their implementation, or possibly use Ant to do what you need.

我没有直接使用tar API,但是tar和bzip2是在Ant中实现的;你可以借用他们的实现,或者可能使用 Ant 来做你需要的。

Gzip is part of Java SE(and I'm guessing the Ant implementation follows the same model).

Gzip 是 Java SE 的一部分(我猜 Ant 实现遵循相同的模型)。

GZIPInputStreamis just an InputStreamdecorator. You can wrap, for example, a FileInputStreamin a GZIPInputStreamand use it in the same way you'd use any InputStream:

GZIPInputStream只是一个InputStream装饰器。例如,您可以将 a 包装FileInputStream在 a 中GZIPInputStream并以与使用 any 相同的方式使用它InputStream

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

(Note that the GZIPInputStream has its own, internal buffer, so wrapping the FileInputStreamin a BufferedInputStreamwould probably decrease performance.)

(请注意, GZIPInputStream 有自己的内部缓冲区,因此将其包装FileInputStream在 a 中BufferedInputStream可能会降低性能。)

回答by Fernando Miguélez

What about using this APIfor tar files, this other oneincluded inside Ant for BZIP2 and the standard onefor GZIP?

将这个API用于 tar 文件,另一个包含在 Ant 中的 BZIP2 和标准的 GZIP 文件怎么样?

回答by J?rg

In addition to gzip and bzip2, Apache Commons Compress APIhas also tar support, originally based on ICE Engineering Java Tar Package, which is both API and standalone tool.

除了 gzip 和 bzip2,Apache Commons Compress API也有 tar 支持,最初基于ICE Engineering Java Tar Package,它既是 API 又是独立工具。

回答by J?rg

Apache Commons VFSsupports tar as a virtual file system, which supports URLs like this one tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt

Apache Commons VFS支持 tar 作为一种虚拟文件系统,它支持像这样的 URL。tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt

TrueZipor its successor TrueVFSdoes the same ... it's also available from Maven Central.

TrueZip或其后继者TrueVFS也做同样的事情……它也可以从 Maven Central 获得。

回答by Renaud

I just tried a bunch of the suggested libs (TrueZip, Apache Compress), but no luck.

我只是尝试了一堆建议的库(TrueZip、Apache Compress),但没有运气。

Here is an example with Apache Commons VFS:

这是 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();
    }
}

And the maven dependency:

和 maven 依赖:

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

回答by Dan Borza

You can do this with the Apache Commons Compress library. You can download the 1.2 version from http://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.2.

您可以使用 Apache Commons Compress 库执行此操作。您可以从http://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.2下载 1.2 版本。

Here are two methods: one that unzips a file and another one that untars it. So, for a file <fileName>tar.gz, you need to first unzip it and after that untar it. Please note that the tar archive may contain folders as well, case in which they need to be created on the local filesystem.

这里有两种方法:一种解压缩文件,另一种解压缩文件。因此,对于文件 <fileName>tar.gz,您需要先解压缩它,然后再解压它。请注意,tar 存档也可能包含文件夹,在这种情况下,它们需要在本地文件系统上创建。

Enjoy.

享受。

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

回答by D3iv

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

Dependency:

依赖:

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

回答by Wade Walker

Here's a version based on this earlier answerby Dan Borza that uses Apache Commons Compressand Java NIO (i.e. Path instead of File). It also does the uncompression and untarring in one stream so there's no intermediate file creation.

这是一个基于Dan Borza较早回答的版本,它使用Apache Commons Compress和 Java NIO(即路径而不是文件)。它还在一个流中进行解压缩和解压,因此没有中间文件创建。

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();
}