Comment extraire un fichier tar (ou tar.gz ou tar.bz2) en Java?
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.)
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;
}
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.
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 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>
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.
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();
}