Question

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

Était-ce utile?

La solution

Remarque: Cette fonctionnalité a été publiée ultérieurement dans un projet distinct, Apache Commons Compress, comme décrit dans un autre réponse. Cette réponse est obsolète.

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 la mise en oeuvre de Ant suit le même modèle).

GZIPInputStream est juste un InputStream décorateur. Vous pouvez, par exemple, insérer un FileInputStream dans un BufferedInputStream et l'utiliser de la même manière que vous utiliseriez n'importe quel <=>:

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

(Notez que GZIPInputStream a son propre tampon interne. Par conséquent, insérer <<> dans un <=> réduirait probablement les performances).

Autres conseils

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 < NomFichier > tar.gz, vous devez d’abord le décompresser, puis 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.

Profitez.

/** 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 prend en charge tar en tant que système de fichiers virtuel , qui supporte les 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 depuis Maven Central.

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>

Je viens d'essayer quelques-unes 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>

En plus de gzip et de bzip2, API de compression Apache Commons est également gérée par tar, elle-même basée à l'origine sur Le package tar Java ICE Engineering , qui est à la fois une API et un outil autonome.

Pourquoi ne pas utiliser cette API pour les fichiers tar, this autre inclus dans Ant pour BZIP2 et standard pour GZIP?

Voici une version basée sur la réponse précédente de Dan Borza qui utilise Apache Commons Compress et Java NIO (c.-à-d. chemin au lieu de fichier). Il effectue également la décompression et la décompression dans un flux, évitant ainsi la création de fichiers intermédiaires.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top