使用Java API進行tar.gz文件及文件夾壓縮解壓縮

      網友投稿 1516 2022-05-29

      在java(JDK)中我們可以使用ZipOutputStream去創建zip壓縮文件,(參考我之前寫的文章 使用java API進行zip遞歸壓縮文件夾以及解壓 ),也可以使用GZIPOutputStream去創建gzip(gz)壓縮文件,但是java中沒有一種官方的API可以去創建tar.gz文件。所以我們需要使用到第三方庫Apache Commons Compress去創建.tar.gz文件。

      在pom.xml中,我們可以通過如下的maven坐標引入commons-compress。

      org.apache.commons commons-compress 1.20

      1

      2

      3

      4

      5

      解釋說明

      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 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(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      將file-a.xml和file-b.txt打包到output.tar文件中,并使用gzip對這個tar包進行壓縮??梢允褂萌缦旅畈榭磘ar包里面包含的文件。

      $ 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

      1

      2

      3

      二、將一個文件夾壓縮為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() { //當成功訪問到一個文件 @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(); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      三、解壓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; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      使用Java API進行tar.gz文件及文件夾壓縮解壓縮

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      API Java 彈性文件服務

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:性能分析之Linux系統平均負載案例分析
      下一篇:萌妹子Python入門指北(二)
      相關文章
      亚洲色图在线播放| 亚洲性日韩精品一区二区三区 | 亚洲免费日韩无码系列| 久久亚洲国产精品成人AV秋霞 | 亚洲伊人久久大香线蕉苏妲己| 亚洲无码高清在线观看| 亚洲欧美黑人猛交群| 亚洲理论片中文字幕电影| 亚洲AV永久无码精品成人| 一区二区三区亚洲视频| 亚洲最大中文字幕无码网站| 亚洲小视频在线观看| 久久精品国产亚洲AV无码偷窥 | 亚洲日韩国产一区二区三区在线 | 亚洲色偷偷综合亚洲AV伊人蜜桃 | 亚洲国产另类久久久精品黑人| 亚洲成a∨人片在无码2023| 亚洲欧洲日产韩国在线| 亚洲成a人不卡在线观看| 亚洲国产片在线观看| 亚洲资源在线观看| 亚洲蜜芽在线精品一区| 亚洲毛片αv无线播放一区| 国产∨亚洲V天堂无码久久久| 亚洲一区无码精品色| 国产美女亚洲精品久久久综合| 亚洲av无码专区在线观看素人| 亚洲欧洲av综合色无码| 亚洲av日韩专区在线观看| 亚洲看片无码在线视频| 亚洲喷奶水中文字幕电影 | 激情综合亚洲色婷婷五月APP| 亚洲综合视频在线观看| 亚洲国产电影在线观看| 亚洲欧美中文日韩视频| 亚洲乱码日产精品a级毛片久久| 狠狠综合久久综合88亚洲| 久久夜色精品国产亚洲AV动态图| 亚洲精品乱码久久久久久自慰 | 亚洲第一se情网站| 亚洲欧美日韩一区二区三区在线|