在java(JDK)中我们可以使用ZipOutputStream去创建zip压缩文件,(参考我之前写的文章 使用java API进行zip递归压缩文件夹以及解压 ),也可以使用GZIPOutputStream去创建gzip(gz)压缩文件,但是java中没有一种官方的API可以去创建tar.gz文件。所以我们需要使用到第三方库Apache Commons Compress去创建.tar.gz文件。

在pom.xml中,我们可以通过如下的maven坐标引入commons-compress。

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>

解释说明

  1. tar文件准确的说是打包文件,将文件打包到一个tar文件中,文件名后缀是.tar
  2. Gzip是将文件的存储空间压缩保存,文件名后缀是.gz
  3. 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.xmlfile-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;
}

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

使用Java API进行tar.gz文件及文件夹压缩解压缩的更多相关文章

  1. Delphi - Windows系统下,Delphi调用API函数和7z.dll动态库,自动把文件压缩成.tar.gz格式的文件

    项目背景 应欧美客户需求,需要将文件压缩成.tar.gz格式的文件,并上传给客户端SFTP服务器. 你懂的,7-Zip软件的显著特点是文件越大压缩比越高,在Linux系统上相当于我们Windows系统 ...

  2. xlslib安装, aclocal-1.13: command not found, 安装升级autoconf-2.65.tar.gz, automake-1.13.tar.gz两个文件

    问题1: $ make CDPATH="${ZSH_VERSION+.}:" && cd . && aclocal-1.13 -I m4 /bin/ ...

  3. 第一章:pip 安装 tar.gz 结尾的文件 和 .whl 结尾的文件

    1. 假如后缀中还有 .tar.gz 的文件通过 pip 命令进行安装步骤. .单击 .tar.gz结尾的文件,并且对文件进行解压,进入到解压目录中,通过python命令进行安装. 命令如下:在dos ...

  4. 如何将文件压缩成.tar.gz格式的文件

    1.下载“7-ZIP“这个软件 2.安装7-ZIP以后,直接在你想要打包的文件上点右键菜单,会有一个7-ZIP的子菜单栏,类似WinRAR和WinZIP的那种右键菜单.然后选“7-ZIP”->“ ...

  5. Linux压缩解压 tar.gz格式的文件.查看tomcat是否运行

    tar命令详解 -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用 ...

  6. linux中解压缩并安装.tar.gz后缀的文件

    1.解压缩: Linux下以tar.gz为扩展名的软件包,是用tar程序打包并用gzip程序压缩的软件包.要安装这种软件包,需要先对软件包进行解压缩,使用“tar -zxfv filename.tar ...

  7. 【java】 java 解压tar.gz读取内容

    package com.xwolf.stat.util; import com.alibaba.druid.util.StringUtils; import com.alibaba.fastjson. ...

  8. 不解压查看tar.gz包内文件

    通过tar命令备份.解压缩文件,也可在不解压缩文件时查看包内的文件信息. 使用如下参数: tar -ztvf file.tar.gz 将列出所有包内的文件列表,包括目录 -z, --gzip, --g ...

  9. tar、7z(7zip)压缩/解压缩指令的使用

    本文介绍tar.7z指令的使用方法 tar指令 在Linux中,使用的最多的压缩/解压缩指令就是tar指令了. tar指令用来将多个文件/目录结构打包.在实际使用中,往往使用tar对压缩的支持,即同时 ...

随机推荐

  1. git安装并与远程仓库关联相关配置

    git是当前最流行的版本控制系统,下面简单记录一下git的安装及其与远程仓库的关联. git安装 打开git官网,下载对应的安装包. 双击运行安装包,安装过程中可以直接选择默认配置,一路next下去. ...

  2. 水题----根据O出现次数判断分数

    There is an objective test result such as \OOXXOXXOOO". An `O' means a correct answer of a prob ...

  3. 如何消灭飞机的“黑色十分钟”,AI来帮忙

    近年来,“AI的应用和落地”逐渐成了具化的关键词,它和很多事物很多行业结合在一起,形成了奇妙的“化学反应”.例如,在日常生活中,AI可以推送我们喜欢的新闻或视频,可以在拍照的时候识别场景提升照片的美感 ...

  4. js POST调用api接口时,由于OPTIONS请求导致服务器异常

    1.学习心得 当你搜到这个问题时,就表示你已经知道了脚本POST请求接口时,会先执行一次OPTIONS类型的请求.至于为什么会这样,在此就不做描述了,想知道的小伙伴可以查一下:本文主要将我在现实中遇到 ...

  5. C/C++编程笔记:C++入门知识丨继承和派生

    本篇要学习的内容和知识结构概览 继承和派生的概念 派生 通过特殊化已有的类来建立新类的过程, 叫做”类的派生”, 原有的类叫做”基类”, 新建立的类叫做”派生类”. 从类的成员角度看, 派生类自动地将 ...

  6. 5.19 省选模拟赛 T1 小B的棋盘 双指针 性质

    LINK:小B的棋盘 考试的时候没有认真的思考 导致没做出来. 容易发现 当k>=n的时候存在无限解 其余都存在有限解 对于30分 容易想到暴力枚举 对称中心 然后 n^2判断. 对于前者 容易 ...

  7. zabbix脚本发送邮件告警

    目录 zabbix邮箱告警 内部使用第三方邮箱发送邮箱告警 zabbix使用第三方邮箱发送告警 通过脚本使用第三方邮箱发送邮箱告警 zabbix邮箱告警 环境说明: zabbix服务端 192.168 ...

  8. Docker管理工具之portainer

    参考:https://www.cnblogs.com/frankdeng/p/9686735.html 1. 查询portainer镜像 命令:docker search portainer 实例: ...

  9. 连接云MariaDB实例

    新建实例 MariaDB CVM 内网连接 CVM远程登录测试(同一个VPC下): CVM安装客户端: yum install mysql 连接: mysql -h MariaDB内网ip -u 数据 ...

  10. mybatis中的延迟查询思想

    1.一对一延迟加载 延迟加载: 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据.延迟加载也称懒加载. 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比 ...