web-dev-qa-db-fra.com

Comment extraire un fichier tar en Java?

Comment extraire un fichier tar (ou tar.gz ou tar.bz2) en Java?

60
skiphoppy

Remarque: Cette fonctionnalité a été publiée ultérieurement par le biais d'un projet distinct, Apache Commons Compress, sous la forme décrit dans une autre réponse. Cette réponse est périmé.


Je n'ai pas utilisé directement une API tar, mais tar et bzip2 sont implémentés dans Ant; vous pouvez emprunter leur implémentation, ou éventuellement utiliser Ant pour faire ce dont vous avez besoin.

Gzip fait partie de Java SE (et je suppose que l'implémentation Ant suit le même modèle).

GZIPInputStream n'est qu'un InputStream décorateur. Vous pouvez encapsuler, par exemple, un FileInputStream dans un GZIPInputStream et l'utiliser de la même manière que vous utiliseriez n'importe quel InputStream:

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

(Notez que le GZIPInputStream a son propre tampon interne, donc le fait d'encapsuler le FileInputStream dans un BufferedInputStream diminuerait probablement les performances.)

19
erickson

Vous pouvez le faire avec la bibliothèque Apache Commons Compress. Vous pouvez télécharger la version 1.2 à partir de http://mvnrepository.com/artifact/org.Apache.commons/commons-compress/1.2 .

Voici deux méthodes: une qui décompresse un fichier et une autre qui le décompresse. Donc, pour un fichier <fileName> tar.gz, vous devez d'abord le décompresser et ensuite le décompresser. Veuillez noter que l'archive tar peut également contenir des dossiers, dans le cas où ils doivent être créés sur le système de fichiers local.

Prendre plaisir.

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

Apache Commons VFS prend en charge tar en tant que système de fichiers virtuel, qui prend en charge des URL comme celle-ci tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt

TrueZip ou son successeur TrueVFS fait de même ... il est également disponible auprès de Maven Central.

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

Dépendance:

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

Je viens d'essayer un tas des bibliothèques suggérées (TrueZip, Apache Compress), mais pas de chance.

Voici un exemple avec 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();
    }
}

Et la dépendance maven:

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

En plus de gzip et bzip2, API Apache Commons Compress prend également en charge tar, à l'origine basé sur ICE Engineering Java Tar Package , qui est API et outil autonome.

6
Jörg

Qu'en est-il de l'utilisation de cette API pour les fichiers tar, cette autre incluse dans Ant pour BZIP2 et la standard pour GZIP?

4
Fernando Miguélez

Voici une version basée sur cette réponse précédente par Dan Borza qui utilise Apache Commons Compress et Java NIO (c'est-à-dire Chemin au lieu de Fichier). Il effectue également la décompression et le décompactage en un seul flux, il n'y a donc pas de création de fichier intermédiaire.

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