BAEL-6403 - Extracting a Tar File in Java (#14240)

* code 1

* sibling module readme

* new module

* review 1

* review 2
This commit is contained in:
Ulisses Lima 2023-06-24 05:43:02 -03:00 committed by GitHub
parent faf6b79e86
commit 7d58a88529
16 changed files with 360 additions and 1 deletions

View File

@ -0,0 +1,7 @@
## Apache Commons
This module contains articles about Apache Commons libraries.
### Relevant articles
- More articles: [[<--prev]](../libraries-apache-commons)

View File

@ -0,0 +1 @@
log4j.rootLogger=INFO, stdout

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>libraries-apache-commons-2</artifactId>
<name>libraries-apache-commons-2</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>${ant.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-vfs2</artifactId>
<version>${commons-vfs2.version}</version>
</dependency>
</dependencies>
<properties>
<commons-compress.version>1.23.0</commons-compress.version>
<ant.version>1.10.13</ant.version>
<commons-vfs2.version>2.9.0</commons-vfs2.version>
</properties>
</project>

View File

@ -0,0 +1,14 @@
package com.baeldung.commons.untar;
import java.io.InputStream;
public interface Resources {
static InputStream tarFile() {
return Resources.class.getResourceAsStream("/untar/test.tar");
}
static InputStream tarGzFile() {
return Resources.class.getResourceAsStream("/untar/test.tar.gz");
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.commons.untar;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
public abstract class TarExtractor {
private InputStream tarStream;
private boolean gzip;
private Path destination;
protected TarExtractor(InputStream in, boolean gzip, Path destination) throws IOException {
this.tarStream = in;
this.gzip = gzip;
this.destination = destination;
Files.createDirectories(destination);
}
protected TarExtractor(Path tarFile, Path destination) throws IOException {
this(Files.newInputStream(tarFile), tarFile.endsWith("gz"), destination);
}
public Path getDestination() {
return destination;
}
public InputStream getTarStream() {
return tarStream;
}
public boolean isGzip() {
return gzip;
}
public abstract void untar() throws IOException;
}

View File

@ -0,0 +1,37 @@
package com.baeldung.commons.untar.impl;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.zip.GZIPInputStream;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;
import com.baeldung.commons.untar.TarExtractor;
public class TarExtractorAnt extends TarExtractor {
public TarExtractorAnt(InputStream in, boolean gzip, Path destination) throws IOException {
super(in, gzip, destination);
}
@Override
public void untar() throws IOException {
try (TarInputStream tar = new TarInputStream(new BufferedInputStream( //
isGzip() ? new GZIPInputStream(getTarStream()) : getTarStream()))) {
TarEntry entry;
while ((entry = tar.getNextEntry()) != null) {
Path extractTo = getDestination().resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectories(extractTo);
} else {
Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
}
}
}
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.commons.untar.impl;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import com.baeldung.commons.untar.TarExtractor;
public class TarExtractorCommonsCompress extends TarExtractor {
public TarExtractorCommonsCompress(InputStream in, boolean gzip, Path destination) throws IOException {
super(in, gzip, destination);
}
@Override
public void untar() throws IOException {
try (BufferedInputStream inputStream = new BufferedInputStream(getTarStream()); //
TarArchiveInputStream tar = new TarArchiveInputStream( //
isGzip() ? new GzipCompressorInputStream(inputStream) : inputStream)) {
ArchiveEntry entry;
while ((entry = tar.getNextEntry()) != null) {
Path extractTo = getDestination().resolve(entry.getName());
if (entry.isDirectory()) {
Files.createDirectories(extractTo);
} else {
Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
}
}
}
}
}

View File

@ -0,0 +1,48 @@
package com.baeldung.commons.untar.impl;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.VFS;
import com.baeldung.commons.untar.TarExtractor;
public class TarExtractorVfs extends TarExtractor {
public TarExtractorVfs(InputStream in, boolean gzip, Path destination) throws IOException {
super(in, gzip, destination);
}
@Override
public void untar() throws IOException {
Path tmpTar = Files.createTempFile("temp", isGzip() ? ".tar.gz" : ".tar");
Files.copy(getTarStream(), tmpTar, StandardCopyOption.REPLACE_EXISTING);
FileSystemManager fsManager = VFS.getManager();
String uri = String.format("%s:file://%s", isGzip() ? "tgz" : "tar", tmpTar);
FileObject tar = fsManager.resolveFile(uri);
for (FileObject entry : tar) {
Path extractTo = Paths.get(getDestination().toString(), entry.getName()
.getPath());
if (entry.isReadable() && entry.getType() == FileType.FILE) {
Files.createDirectories(extractTo.getParent());
try (FileContent content = entry.getContent(); InputStream stream = content.getInputStream()) {
Files.copy(stream, extractTo, StandardCopyOption.REPLACE_EXISTING);
}
}
}
Files.delete(tmpTar);
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,40 @@
package com.baeldung.commons.untar;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.junit.Test;
import com.baeldung.commons.untar.impl.TarExtractorAnt;
public class TarExtractorAntUnitTest {
@Test
public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
Path destination = Paths.get("/tmp/ant");
new TarExtractorAnt(Resources.tarFile(), false, destination).untar();
try (Stream<Path> files = Files.list(destination)) {
assertTrue(files.findFirst()
.isPresent());
}
}
@Test
public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
Path destination = Paths.get("/tmp/ant-gz");
new TarExtractorAnt(Resources.tarGzFile(), true, destination).untar();
try (Stream<Path> files = Files.list(destination)) {
assertTrue(files.findFirst()
.isPresent());
}
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.commons.untar;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import com.baeldung.commons.untar.impl.TarExtractorCommonsCompress;
public class TarExtractorCommonsCompressUnitTest {
@Test
public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
Path destination = Paths.get("/tmp/commons-compress");
new TarExtractorCommonsCompress(Resources.tarFile(), false, destination).untar();
try (Stream<Path> files = Files.list(destination)) {
assertTrue(files.findFirst()
.isPresent());
}
}
@Test
public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
Path destination = Paths.get("/tmp/commons-compress-gz");
new TarExtractorCommonsCompress(Resources.tarGzFile(), true, destination).untar();
try (Stream<Path> files = Files.list(destination)) {
assertTrue(files.findFirst()
.isPresent());
}
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.commons.untar;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import org.junit.Test;
import com.baeldung.commons.untar.impl.TarExtractorVfs;
public class TarExtractorVfsUnitTest {
@Test
public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
Path destination = Paths.get("/tmp/vfs");
new TarExtractorVfs(Resources.tarFile(), false, destination).untar();
try (Stream<Path> files = Files.list(destination)) {
assertTrue(files.findFirst()
.isPresent());
}
}
@Test
public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
Path destination = Paths.get("/tmp/vfs-gz");
new TarExtractorVfs(Resources.tarGzFile(), true, destination).untar();
try (Stream<Path> files = Files.list(destination)) {
assertTrue(files.findFirst()
.isPresent());
}
}
}

View File

@ -14,3 +14,4 @@ This module contains articles about Apache Commons libraries.
- [Histograms with Apache Commons Frequency](https://www.baeldung.com/apache-commons-frequency)
- [An Introduction to Apache Commons Lang 3](https://www.baeldung.com/java-commons-lang-3)
- [Differences Between the Java WatchService API and the Apache Commons IO Monitor Library](https://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library)
More articles: [[next-->]](../libraries-apache-commons-2)

View File

@ -867,6 +867,7 @@
<module>libraries-6</module>
<module>libraries-apache-commons</module>
<module>libraries-apache-commons-2</module>
<module>libraries-apache-commons-collections</module>
<module>libraries-apache-commons-io</module>
<module>libraries-data-2</module>
@ -1135,6 +1136,7 @@
<module>libraries-5</module>
<module>libraries-6</module>
<module>libraries-apache-commons</module>
<module>libraries-apache-commons-2</module>
<module>libraries-apache-commons-collections</module>
<module>libraries-apache-commons-io</module>
<module>libraries-data-2</module>