Java 解析 Linux 不同压缩文件的方法及注意事项

背景

commons-compress 包提供了归档压缩文件的工具类,java.util 里面包含了 Zip 和 gz 文件的解压方法,最终以按扁平方式,遍历到全部文件的文件,包括子目录下的文件。使用 Java 实现的日志采集系统涉及到对压缩文件的解析,不同类型的压缩文件,Java 解析方式也不相同,本文整理 Java 解析四类常见压缩文件的方法及注意事项。

关键点在于辨别压缩文件的类型及对应生成命令,确保文件名称的后缀名和生成工具保持一致,否则容易出现解析异常,总结几个点就是:

  1. tar -cvf 生成的普通打包文件,后缀名为 .tar ,文件只归档,不压缩,文件较大。
  2. tar -czvf-z 参数代表用 gzip 压缩,生成 tar.gz 压缩的归档文件。
  3. zip -r 生成的 .zip 压缩文件,可以对目录进行压缩。
  4. gzip 文件名称,单文件压缩工具,对目标文件压缩后生成 .gz 的文件,且删除原文件。

四种压缩方式,入参压缩文件输入流 commpressIns 的各种压缩方式的读取流程。

tar

tar 命令生成的无压缩归档文件,体积比较大,一般不单独使用,它的解析方式为:

java 复制代码
public void parseTarGzFile(InputStream commpressIns) {
	TarArchiveInputStream archiveInputStream = new TarArchiveInputStream(commpressIns, "UTF-8");
    InputStreamReader inputStreamReader = null;
	TarArchiveEntry currentEntry;
    try {
          currentEntry = (TarArchiveEntry) archiveInputStream.getNextEntry();
          // 循环遍历归档条目
          while (currentEntry != null) {
              String subfileName = currentEntry.getName();
 
              inputStreamReader = new InputStreamReader(archiveInputStream)
              // TODO inputStreamReader 逐行读取当前压缩文件条目的内容
         }
    } catch (Exception e) {
        // TODO error 
    }    
}

使用 TarArchiveInputStream 它直接将压缩文件的各个文件都递归列出来,逐个读取就可完成遍历,它跟 zip 文件不一样,文件夹不会被作为一个 Entry ,所以还是比较容易的。

tar.gz

使用 tar -zc 生成的压缩文件,它有两种特性,一个是归档,二是 gzip 的压缩格式,流程与 tar 文件解析一致,但是需要包裹一层 GZip 输入流:

java 复制代码
public void parseTarGzFile(InputStream commpressIns) {
    // 用 gzip 包裹一层
    GZIPInputStream gzInstream = new GZIPInputStream(commpressIns);
	TarArchiveInputStream archiveInputStream = new TarArchiveInputStream(gzInstream, "UTF-8");
    InputStreamReader inputStreamReader = null;
	TarArchiveEntry currentEntry;
    try {
          currentEntry = (TarArchiveEntry) archiveInputStream.getNextEntry();
          // 循环遍历归档条目
          while (currentEntry != null) {
              String subfileName = currentEntry.getName();
 
              inputStreamReader = new InputStreamReader(archiveInputStream)
         
        // TODO inputStreamReader 逐行读取当前压缩文件条目的内容
        }
    } catch (Exception e) {
        // TODO error 
    }    
}

必须使用 tar -z 参数生成的文件,用 TarArchiveInputStream 解析时传入的是 GZIPInputStream 类型,否则非 gzip 压缩的 tar 文件,解析时会包 「非 Gzip Format 」异常 。

zip

zip -r 对文件夹压缩产生的的 zip 文件用 ZipInputStream 解析 。

java 复制代码
public void parseZipFile(InputStream commpressIns) {
	ZipInputStream zipStream = new ZipInputStream(commpressIns);
    ZipEntry entry;
    InputStreamReader inputStreamReader = null;

    while ((entry = zis.getNextEntry()) != null) {
        // 注意事项:忽略文件夹名称条目
        String fileName = entry.getName();
        if (fileName.endsWith("/")) {
            continue;
        }
        
        inputStreamReader = new InputStreamReader(zipStream, "UTF-8");

        // TODO inputStreamReader 逐行读取当前压缩文件条目的内容
    }
}

ZipInputStream 会以递归压缩文件,最终扁平化对所有文件形成一个链表,启动文件夹也会作为一个 ZipEntry ,以 / 结尾,实际内容为空,所以解析时忽略即可。

gz

gzip 读单个文件生成的压缩文件解析比较简单:

java 复制代码
public void parseGzipFile(InputStream commpressIns) {
    GZIPInputStream gzipInput = new GZIPInputStream(commpressIns);
    InputStreamReader reader = new InputStreamReader(gzipInput, "UTF-8");

    // TODO 直接逐行读取文件内容
}       

直接转换为 GZIPInputStream 就可以读取文件内容了。

启示录

zip 的解析目录中存在文件夹的条目,这点跟 tar 归档方式不同,需要注意。此外,解压工具会对文件格式进行校验,当文件后缀和文件格式不一致时,解析异常,需要特别注意。

比如我常用 tar -cvf 打包文件但是命名为 tar.gz ,之前没有特别留意过,直到解析异常。为止防手滑,专门分析四类压缩文件的生成方式及解析方法,整理成文、以备后用。

相关推荐
nlog3n2 小时前
Java策略模式详解
java·bash·策略模式
Mryan20054 小时前
解决GraalVM Native Maven Plugin错误:JAVA_HOME未指向GraalVM Distribution
java·开发语言·spring boot·maven
VX_CXsjNo15 小时前
免费送源码:Java+SSM+Android Studio 基于Android Studio游戏搜索app的设计与实现 计算机毕业设计原创定制
java·spring boot·spring·游戏·eclipse·android studio·android-studio
ylfhpy5 小时前
Java面试黄金宝典33
java·开发语言·数据结构·面试·职场和发展·排序算法
乘风!5 小时前
Java导出excel,表格插入pdf附件,以及实现过程中遇见的坑
java·pdf·excel
小小鸭程序员5 小时前
Vue组件化开发深度解析:Element UI与Ant Design Vue对比实践
java·vue.js·spring·ui·elementui
南宫生6 小时前
Java迭代器【设计模式之迭代器模式】
java·学习·设计模式·kotlin·迭代器模式
seabirdssss6 小时前
通过动态获取项目的上下文路径来确保请求的 URL 兼容两种启动方式(IDEA 启动和 Tomcat 部署)下都能正确解析
java·okhttp·tomcat·intellij-idea
kill bert6 小时前
第30周Java分布式入门 消息队列 RabbitMQ
java·分布式·java-rabbitmq
穿林鸟7 小时前
Spring Boot项目信创国产化适配指南
java·spring boot·后端