Java で tar (または tar.gz、または tar.bz2) ファイルを抽出するにはどうすればよいですか?
8 に答える
これは、Apache Commons Compress ライブラリを使用して実行できます。1.2 バージョンはhttp://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.2からダウンロードできます。
ファイルを解凍する方法と、ファイルを解凍する方法の 2 つがあります。したがって、ファイル <fileName>tar.gz の場合は、最初に解凍し、その後解凍する必要があります。tar アーカイブにはフォルダーも含まれている可能性があることに注意してください。その場合、ローカル ファイルシステムにフォルダーを作成する必要があります。
楽しみ。
/** 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 Compress を通じて公開されました。この回答は古くなっています。
tar API を直接使用したことはありませんが、tar と bzip2 は Ant に実装されています。彼らの実装を借りるか、Ant を使用して必要なことを行うことができます。
Gzip は Java SE の一部です (Ant の実装も同じモデルに従っていると思います)。
GZIPInputStream
単なるInputStream
デコレータです。たとえば、 aFileInputStream
を a にラップGZIPInputStream
して、 any を使用するのと同じ方法で使用できますInputStream
。
InputStream is = new GZIPInputStream(new FileInputStream(file));
(GZIPInputStream には独自の内部バッファーがあるため、 を a でラップすると、おそらくパフォーマンスが低下することに注意してくださいFileInputStream
。BufferedInputStream
)
Apache Commons VFSは、このような URL をサポートする仮想ファイル システムとして tarをサポートします。tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt
TrueZipまたはその後継のTrueVFSも同じことを行います... Maven Central からも入手できます。
提案されたライブラリ(TrueZip、Apache Compress)を試しましたが、うまくいきませんでした。
次に、ApacheCommonsVFSの例を示します。
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();
}
}
そして、Mavenの依存関係:
<dependency>
<groupId>commons-vfs</groupId>
<artifactId>commons-vfs</artifactId>
<version>1.0</version>
</dependency>
gzip と bzip2 に加えて、Apache Commons Compress APIには tar サポートもあり、元々は API とスタンドアロン ツールの両方であるICE Engineering Java Tar Packageに基づいていました。
このAPIを tar ファイルに使用するのはどうですか? Ant 内に含まれるこの別のAPI は BZIP2 用で、標準の APIは GZIP 用ですか?
これは、 Apache Commons Compressと Java NIO (つまり、File ではなく Path)を使用する、Dan Borza による以前の回答に基づくバージョンです。また、1 つのストリームで解凍と untar を行うため、途中でファイルが作成されることはありません。
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();
}