Skip to content

Commit 7d58a88

Browse files
authored
BAEL-6403 - Extracting a Tar File in Java (#14240)
* code 1 * sibling module readme * new module * review 1 * review 2
1 parent faf6b79 commit 7d58a88

File tree

16 files changed

+360
-1
lines changed

16 files changed

+360
-1
lines changed

libraries-apache-commons-2/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## Apache Commons
2+
3+
This module contains articles about Apache Commons libraries.
4+
5+
### Relevant articles
6+
7+
- More articles: [[<--prev]](../libraries-apache-commons)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
log4j.rootLogger=INFO, stdout

libraries-apache-commons-2/pom.xml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<artifactId>libraries-apache-commons-2</artifactId>
7+
<name>libraries-apache-commons-2</name>
8+
9+
<parent>
10+
<groupId>com.baeldung</groupId>
11+
<artifactId>parent-modules</artifactId>
12+
<version>1.0.0-SNAPSHOT</version>
13+
</parent>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>org.apache.commons</groupId>
18+
<artifactId>commons-compress</artifactId>
19+
<version>${commons-compress.version}</version>
20+
</dependency>
21+
<dependency>
22+
<groupId>org.apache.ant</groupId>
23+
<artifactId>ant</artifactId>
24+
<version>${ant.version}</version>
25+
</dependency>
26+
<dependency>
27+
<groupId>org.apache.commons</groupId>
28+
<artifactId>commons-vfs2</artifactId>
29+
<version>${commons-vfs2.version}</version>
30+
</dependency>
31+
</dependencies>
32+
33+
<properties>
34+
<commons-compress.version>1.23.0</commons-compress.version>
35+
<ant.version>1.10.13</ant.version>
36+
<commons-vfs2.version>2.9.0</commons-vfs2.version>
37+
</properties>
38+
39+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.baeldung.commons.untar;
2+
3+
import java.io.InputStream;
4+
5+
public interface Resources {
6+
7+
static InputStream tarFile() {
8+
return Resources.class.getResourceAsStream("/untar/test.tar");
9+
}
10+
11+
static InputStream tarGzFile() {
12+
return Resources.class.getResourceAsStream("/untar/test.tar.gz");
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.baeldung.commons.untar;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
8+
public abstract class TarExtractor {
9+
10+
private InputStream tarStream;
11+
private boolean gzip;
12+
private Path destination;
13+
14+
protected TarExtractor(InputStream in, boolean gzip, Path destination) throws IOException {
15+
this.tarStream = in;
16+
this.gzip = gzip;
17+
this.destination = destination;
18+
19+
Files.createDirectories(destination);
20+
}
21+
22+
protected TarExtractor(Path tarFile, Path destination) throws IOException {
23+
this(Files.newInputStream(tarFile), tarFile.endsWith("gz"), destination);
24+
}
25+
26+
public Path getDestination() {
27+
return destination;
28+
}
29+
30+
public InputStream getTarStream() {
31+
return tarStream;
32+
}
33+
34+
public boolean isGzip() {
35+
return gzip;
36+
}
37+
38+
public abstract void untar() throws IOException;
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.baeldung.commons.untar.impl;
2+
3+
import java.io.BufferedInputStream;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.StandardCopyOption;
9+
import java.util.zip.GZIPInputStream;
10+
11+
import org.apache.tools.tar.TarEntry;
12+
import org.apache.tools.tar.TarInputStream;
13+
14+
import com.baeldung.commons.untar.TarExtractor;
15+
16+
public class TarExtractorAnt extends TarExtractor {
17+
18+
public TarExtractorAnt(InputStream in, boolean gzip, Path destination) throws IOException {
19+
super(in, gzip, destination);
20+
}
21+
22+
@Override
23+
public void untar() throws IOException {
24+
try (TarInputStream tar = new TarInputStream(new BufferedInputStream( //
25+
isGzip() ? new GZIPInputStream(getTarStream()) : getTarStream()))) {
26+
TarEntry entry;
27+
while ((entry = tar.getNextEntry()) != null) {
28+
Path extractTo = getDestination().resolve(entry.getName());
29+
if (entry.isDirectory()) {
30+
Files.createDirectories(extractTo);
31+
} else {
32+
Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
33+
}
34+
}
35+
}
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.baeldung.commons.untar.impl;
2+
3+
import java.io.BufferedInputStream;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.StandardCopyOption;
9+
10+
import org.apache.commons.compress.archivers.ArchiveEntry;
11+
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
12+
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
13+
14+
import com.baeldung.commons.untar.TarExtractor;
15+
16+
public class TarExtractorCommonsCompress extends TarExtractor {
17+
18+
public TarExtractorCommonsCompress(InputStream in, boolean gzip, Path destination) throws IOException {
19+
super(in, gzip, destination);
20+
}
21+
22+
@Override
23+
public void untar() throws IOException {
24+
try (BufferedInputStream inputStream = new BufferedInputStream(getTarStream()); //
25+
TarArchiveInputStream tar = new TarArchiveInputStream( //
26+
isGzip() ? new GzipCompressorInputStream(inputStream) : inputStream)) {
27+
ArchiveEntry entry;
28+
while ((entry = tar.getNextEntry()) != null) {
29+
Path extractTo = getDestination().resolve(entry.getName());
30+
if (entry.isDirectory()) {
31+
Files.createDirectories(extractTo);
32+
} else {
33+
Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
34+
}
35+
}
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.baeldung.commons.untar.impl;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.nio.file.Files;
6+
import java.nio.file.Path;
7+
import java.nio.file.Paths;
8+
import java.nio.file.StandardCopyOption;
9+
10+
import org.apache.commons.vfs2.FileContent;
11+
import org.apache.commons.vfs2.FileObject;
12+
import org.apache.commons.vfs2.FileSystemManager;
13+
import org.apache.commons.vfs2.FileType;
14+
import org.apache.commons.vfs2.VFS;
15+
16+
import com.baeldung.commons.untar.TarExtractor;
17+
18+
public class TarExtractorVfs extends TarExtractor {
19+
20+
public TarExtractorVfs(InputStream in, boolean gzip, Path destination) throws IOException {
21+
super(in, gzip, destination);
22+
}
23+
24+
@Override
25+
public void untar() throws IOException {
26+
Path tmpTar = Files.createTempFile("temp", isGzip() ? ".tar.gz" : ".tar");
27+
Files.copy(getTarStream(), tmpTar, StandardCopyOption.REPLACE_EXISTING);
28+
29+
FileSystemManager fsManager = VFS.getManager();
30+
String uri = String.format("%s:file://%s", isGzip() ? "tgz" : "tar", tmpTar);
31+
FileObject tar = fsManager.resolveFile(uri);
32+
33+
for (FileObject entry : tar) {
34+
Path extractTo = Paths.get(getDestination().toString(), entry.getName()
35+
.getPath());
36+
37+
if (entry.isReadable() && entry.getType() == FileType.FILE) {
38+
Files.createDirectories(extractTo.getParent());
39+
40+
try (FileContent content = entry.getContent(); InputStream stream = content.getInputStream()) {
41+
Files.copy(stream, extractTo, StandardCopyOption.REPLACE_EXISTING);
42+
}
43+
}
44+
}
45+
46+
Files.delete(tmpTar);
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<configuration>
3+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
4+
<encoder>
5+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
6+
</pattern>
7+
</encoder>
8+
</appender>
9+
10+
<root level="INFO">
11+
<appender-ref ref="STDOUT" />
12+
</root>
13+
</configuration>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.baeldung.commons.untar;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.Paths;
9+
import java.util.stream.Stream;
10+
11+
import org.junit.Test;
12+
13+
import com.baeldung.commons.untar.impl.TarExtractorAnt;
14+
15+
public class TarExtractorAntUnitTest {
16+
17+
@Test
18+
public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
19+
Path destination = Paths.get("/tmp/ant");
20+
21+
new TarExtractorAnt(Resources.tarFile(), false, destination).untar();
22+
23+
try (Stream<Path> files = Files.list(destination)) {
24+
assertTrue(files.findFirst()
25+
.isPresent());
26+
}
27+
}
28+
29+
@Test
30+
public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
31+
Path destination = Paths.get("/tmp/ant-gz");
32+
33+
new TarExtractorAnt(Resources.tarGzFile(), true, destination).untar();
34+
35+
try (Stream<Path> files = Files.list(destination)) {
36+
assertTrue(files.findFirst()
37+
.isPresent());
38+
}
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.baeldung.commons.untar;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.Paths;
9+
import java.util.stream.Stream;
10+
11+
import org.junit.jupiter.api.Test;
12+
13+
import com.baeldung.commons.untar.impl.TarExtractorCommonsCompress;
14+
15+
public class TarExtractorCommonsCompressUnitTest {
16+
17+
@Test
18+
public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
19+
Path destination = Paths.get("/tmp/commons-compress");
20+
21+
new TarExtractorCommonsCompress(Resources.tarFile(), false, destination).untar();
22+
23+
try (Stream<Path> files = Files.list(destination)) {
24+
assertTrue(files.findFirst()
25+
.isPresent());
26+
}
27+
}
28+
29+
@Test
30+
public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
31+
Path destination = Paths.get("/tmp/commons-compress-gz");
32+
33+
new TarExtractorCommonsCompress(Resources.tarGzFile(), true, destination).untar();
34+
35+
try (Stream<Path> files = Files.list(destination)) {
36+
assertTrue(files.findFirst()
37+
.isPresent());
38+
}
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.baeldung.commons.untar;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.Paths;
9+
import java.util.stream.Stream;
10+
11+
import org.junit.Test;
12+
13+
import com.baeldung.commons.untar.impl.TarExtractorVfs;
14+
15+
public class TarExtractorVfsUnitTest {
16+
17+
@Test
18+
public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
19+
Path destination = Paths.get("/tmp/vfs");
20+
21+
new TarExtractorVfs(Resources.tarFile(), false, destination).untar();
22+
23+
try (Stream<Path> files = Files.list(destination)) {
24+
assertTrue(files.findFirst()
25+
.isPresent());
26+
}
27+
}
28+
29+
@Test
30+
public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
31+
Path destination = Paths.get("/tmp/vfs-gz");
32+
33+
new TarExtractorVfs(Resources.tarGzFile(), true, destination).untar();
34+
35+
try (Stream<Path> files = Files.list(destination)) {
36+
assertTrue(files.findFirst()
37+
.isPresent());
38+
}
39+
}
40+
}
Binary file not shown.
Binary file not shown.

libraries-apache-commons/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ This module contains articles about Apache Commons libraries.
1313
- [Apache Commons BeanUtils](https://www.baeldung.com/apache-commons-beanutils)
1414
- [Histograms with Apache Commons Frequency](https://www.baeldung.com/apache-commons-frequency)
1515
- [An Introduction to Apache Commons Lang 3](https://www.baeldung.com/java-commons-lang-3)
16-
- [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)
16+
- [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)
17+
More articles: [[next-->]](../libraries-apache-commons-2)

0 commit comments

Comments
 (0)