使用Java API進行tar.gz檔案及資料夾壓縮解壓縮
在java(JDK)中我們可以使用ZipOutputStream
去建立zip壓縮檔案,(參考我之前寫的文章 ),也可以使用GZIPOutputStream
去建立gzip(gz)壓縮檔案,但是java中沒有一種官方的API可以去建立tar.gz
檔案。所以我們需要使用到第三方庫去建立.tar.gz
檔案。
在pom.xml中,我們可以透過如下的maven座標引入commons-compress。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
解釋說明
- tar檔案準確的說是打包檔案,將檔案打包到一個tar檔案中,檔名字尾是
.tar
- Gzip是將檔案的儲存空間壓縮儲存,檔名字尾是
.gz
-
tar.gz
或.tgz
通常是指將檔案打包到一個tar檔案中,並將它使用Gzip進行壓縮。
如果您閱讀完本文覺得對您有幫助的話,請給我一個贊,您的支援是我不竭的創作動力!
一、將兩個檔案打包到tar.gz
下面的這個例子是將2個檔案打包為tar.gz
壓縮檔案。下文程式碼中的流操作使用了try-with-resources語法,所以不用寫程式碼手動的close流。
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.junit.jupiter.api.Test;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
public class TarGzTest {
@Test
void testFilesTarGzip() throws IOException {
//輸入檔案,被壓縮檔案
Path path1 = Paths.get("/home/test/file-a.xml");
Path path2 = Paths.get("/home/test/file-b.txt");
List<Path> paths = Arrays.asList(path1, path2);
//輸出檔案壓縮結果
Path output = Paths.get("/home/test/output.tar.gz");
//OutputStream輸出流、BufferedOutputStream緩衝輸出流
//GzipCompressorOutputStream是gzip壓縮輸出流
//TarArchiveOutputStream打tar包輸出流(包含gzip壓縮輸出流)
try (OutputStream fOut = Files.newOutputStream(output);
BufferedOutputStream buffOut = new BufferedOutputStream(fOut);
GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(buffOut);
TarArchiveOutputStream tOut = new TarArchiveOutputStream(gzOut)) {
//遍歷檔案list
for (Path path : paths) {
//該檔案不是目錄或者符號連結
if (!Files.isRegularFile(path)) {
throw new IOException("Support only file!");
}
//將該檔案放入tar包,並執行gzip壓縮
TarArchiveEntry tarEntry = new TarArchiveEntry(
path.toFile(),
path.getFileName().toString());
tOut.putArchiveEntry(tarEntry);
Files.copy(path, tOut);
tOut.closeArchiveEntry();
}
//for迴圈完成之後,finish-tar包輸出流
tOut.finish();
}
}
}
將file-a.xml
和file-b.txt
打包到output.tar
檔案中,並使用gzip對這個tar包進行壓縮。可以使用如下命令檢視tar包裡面包含的檔案。
$ tar -tvf /home/test/output.tar.gz
-rw-r--r-- 0/0 23546 2020-08-17 12:07 file-a.xml
-rw-r--r-- 0/0 34 2020-08-17 12:36 file-b.txt
二、將一個資料夾壓縮為tar.gz
下面的例子將一個資料夾,包含其子資料夾的檔案或子目錄,打包為tar,並使用gzip進行壓縮。最終成為一個tar.gz打包壓縮檔案。
其核心原理是:使用到Files.walkFileTree
依次遍歷檔案目錄樹中的檔案,將其一個一個的新增到TarArchiveOutputStream
.輸出流。
@Test
void testDirTarGzip() throws IOException {
// 被壓縮打包的資料夾
Path source = Paths.get("/home/test");
//如果不是資料夾丟擲異常
if (!Files.isDirectory(source)) {
throw new IOException("請指定一個資料夾");
}
//壓縮之後的輸出檔名稱
String tarFileName = "/home/" + source.getFileName().toString() + ".tar.gz";
//OutputStream輸出流、BufferedOutputStream緩衝輸出流
//GzipCompressorOutputStream是gzip壓縮輸出流
//TarArchiveOutputStream打tar包輸出流(包含gzip壓縮輸出流)
try (OutputStream fOut = Files.newOutputStream(Paths.get(tarFileName));
BufferedOutputStream buffOut = new BufferedOutputStream(fOut);
GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(buffOut);
TarArchiveOutputStream tOut = new TarArchiveOutputStream(gzOut)) {
//遍歷檔案目錄樹
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
//當成功訪問到一個檔案
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attributes) throws IOException {
// 判斷當前遍歷檔案是不是符號連結(快捷方式),不做打包壓縮處理
if (attributes.isSymbolicLink()) {
return FileVisitResult.CONTINUE;
}
//獲取當前遍歷檔名稱
Path targetFile = source.relativize(file);
//將該檔案打包壓縮
TarArchiveEntry tarEntry = new TarArchiveEntry(
file.toFile(), targetFile.toString());
tOut.putArchiveEntry(tarEntry);
Files.copy(file, tOut);
tOut.closeArchiveEntry();
//繼續下一個遍歷檔案處理
return FileVisitResult.CONTINUE;
}
//當前遍歷檔案訪問失敗
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.printf("無法對該檔案壓縮打包為tar.gz : %s%n%s%n", file, exc);
return FileVisitResult.CONTINUE;
}
});
//for迴圈完成之後,finish-tar包輸出流
tOut.finish();
}
}
三、解壓tar.gz壓縮檔案
下面一個例子說明如何解壓一個tar.gz
檔案,具體內容請看程式碼註釋。
@Test
void testDeCompressTarGzip() throws IOException {
//解壓檔案
Path source = Paths.get("/home/test/output.tar.gz");
//解壓到哪
Path target = Paths.get("/home/test2");
if (Files.notExists(source)) {
throw new IOException("您要解壓的檔案不存在");
}
//InputStream輸入流,以下四個流將tar.gz讀取到記憶體並操作
//BufferedInputStream緩衝輸入流
//GzipCompressorInputStream解壓輸入流
//TarArchiveInputStream解tar包輸入流
try (InputStream fi = Files.newInputStream(source);
BufferedInputStream bi = new BufferedInputStream(fi);
GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);
TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {
ArchiveEntry entry;
while ((entry = ti.getNextEntry()) != null) {
//獲取解壓檔案目錄,並判斷檔案是否損壞
Path newPath = zipSlipProtect(entry, target);
if (entry.isDirectory()) {
//建立解壓檔案目錄
Files.createDirectories(newPath);
} else {
//再次校驗解壓檔案目錄是否存在
Path parent = newPath.getParent();
if (parent != null) {
if (Files.notExists(parent)) {
Files.createDirectories(parent);
}
}
// 將解壓檔案輸入到TarArchiveInputStream,輸出到磁碟newPath目錄
Files.copy(ti, newPath, StandardCopyOption.REPLACE_EXISTING);
}
}
}
}
//判斷壓縮檔案是否被損壞,並返回該檔案的解壓目錄
private Path zipSlipProtect(ArchiveEntry entry,Path targetDir)
throws IOException {
Path targetDirResolved = targetDir.resolve(entry.getName());
Path normalizePath = targetDirResolved.normalize();
if (!normalizePath.startsWith(targetDir)) {
throw new IOException("壓縮檔案已被損壞: " + entry.getName());
}
return normalizePath;
}
歡迎關注我的部落格,裡面有很多精品合集
- 本文轉載註明出處(必須帶連線,不能只轉文字):。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/964/viewspace-2826057/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用java API進行zip遞迴壓縮資料夾以及解壓JavaAPI遞迴
- java 壓縮(解壓)檔案或者資料夾工具類Java
- Java實現解壓縮檔案和資料夾Java
- 使用libzip壓縮檔案和資料夾
- Linux加密壓縮檔案/資料夾Linux加密
- linux 下壓縮與解壓資料夾Linux
- 檔案壓縮和解壓縮
- Java實現壓縮資料夾Java
- .NET 壓縮/解壓檔案
- c# 上傳壓縮包 解壓,遍歷資料夾和檔案C#
- 電腦怎麼壓縮檔案 檔案壓縮方法詳解
- betterzip怎麼解壓檔案?如何使用BetterZip批次解壓壓縮檔案
- 分卷壓縮怎麼解壓 快速解壓電腦分卷壓縮檔案方法
- tar解壓到指定目錄並去掉壓縮檔案的層級資料夾
- linux 下面壓縮、解壓.rar檔案Linux
- Linux中Bin檔案壓縮包解壓執行Linux
- Linux中檔案的壓縮和解壓縮Linux
- tar.gz壓縮命令使用方法
- Linux科研武器庫 - 檔案壓縮與解壓縮 - zip / unzipLinux
- Linux下檔案的壓縮與解壓Linux
- PE檔案格式詳細解析(四)-- 執行時壓縮及UPX壓縮除錯除錯
- Linux 檔案壓縮Linux
- gulp壓縮檔案
- java中檔案如何加密壓縮?Java加密
- java中 檔案壓縮處理Java
- java 生成 zip格式 壓縮檔案Java
- java 把檔案壓縮成 zipJava
- 哈夫曼實現檔案壓縮解壓縮(c語言)C語言
- JS壓縮方法及批量壓縮JS
- linux檔案壓縮和解壓命令Linux
- linux系統壓縮,解壓檔案筆記Linux筆記
- linux 高效壓縮工具之xz的壓縮解壓使用Linux
- 使用Rust的ripunzip和rayon並行解壓縮檔案Rust並行
- 初級:如何在 Linux 中 zip 壓縮檔案和資料夾Linux
- 工作經驗: linux 壓縮當前資料夾下所有檔案Linux
- Linux常用命令之檔案壓縮與解壓縮命令詳解Linux
- Windows的壓縮資料夾(zip/cab)Windows
- 怎麼把資料夾壓縮成壓縮包發給微信好友