¿Cómo extraer un archivo tar en Java?
Pregunta
¿Cómo puedo extracto de alquitrán (o tar.gz o alquitrán.bz2) archivo en Java?
Solución
Nota: Esta funcionalidad fue publicado más tarde a través de un proyecto independiente, Apache Commons Comprimir, como se describe en otra respuesta. Esta respuesta está fuera de fecha.
No he utilizado un tar de la API directamente, pero alquitrán y bzip2 se implementan en la Hormiga;usted puede pedir prestado de su aplicación, o, posiblemente, el uso de la Hormiga para hacer lo que usted necesita.
Gzip es parte de Java SE (y supongo que la de la Hormiga de la aplicación sigue el mismo modelo).
GZIPInputStream
es sólo un InputStream
decorador.Usted puede ajustar, por ejemplo, un FileInputStream
en un GZIPInputStream
y el uso que de la misma manera que utilizaría cualquier InputStream
:
InputStream is = new GZIPInputStream(new FileInputStream(file));
(Tenga en cuenta que el GZIPInputStream tiene su propio búfer interno, de manera de envolver el FileInputStream
en un BufferedInputStream
probablemente disminuir el rendimiento.)
Otros consejos
Puede hacer esto con la biblioteca Apache Commons Compress. Puede descargar la versión 1.2 desde http://mvnrepository.com/artifact/ org.apache.commons / commons-compress / 1.2 .
Aquí hay dos métodos: uno que descomprime un archivo y otro que lo descomprime. Entonces, para un archivo < fileName > tar.gz, primero debe descomprimirlo y luego descomprimirlo. Tenga en cuenta que el archivo tar también puede contener carpetas, en caso de que necesiten crearse en el sistema de archivos local.
Disfruta.
/** 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 admite tar como un sistema de archivos virtual , que admite URL como esta tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt
TrueZip o su sucesor TrueVFS hace lo mismo ... también está disponible en Maven Central.
Archiver archiver = ArchiverFactory.createArchiver("tar", "gz");
archiver.extract(archiveFile, destDir);
Dependencia:
<dependency>
<groupId>org.rauschig</groupId>
<artifactId>jarchivelib</artifactId>
<version>0.5.0</version>
</dependency>
Acabo de probar algunas de las librerías sugeridas (TrueZip, Apache Compress), pero no tuve suerte.
Aquí hay un ejemplo con 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();
}
}
Y la dependencia de Maven:
<dependency>
<groupId>commons-vfs</groupId>
<artifactId>commons-vfs</artifactId>
<version>1.0</version>
</dependency>
Además de gzip y bzip2, Apache Commons Compress API también tiene soporte de tar, originalmente basado en ICE Engineering Java Tar Package , que es una API y una herramienta independiente.
Aquí hay una versión basada en esta respuesta anterior de Dan Borza que usa Apache Commons Compress y Java NIO (es decir, Path en lugar de File). También realiza la descompresión y descompresión en una secuencia, por lo que no hay creación de archivos intermedios.
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();
}