Java GZip 基于磁盘实现压缩和解压的方法
gzip是常用的无损压缩算法实现,在linux中较为常见,像我们在linux安装软件时,基本都是.tar.gz格式。.tar.gz格式文件需要先对目录内文件进行tar压缩,然后使用gzip进行压缩。
本文针对基于磁盘的压缩和解压进行演示,演示只针对一层目录结构进行,多层目录只需递归操作进行即可。
maven依赖
org.apache.commons: commons-compress: 1.19: 此依赖封装了很多压缩算法相关的工具类,提供的api还是相对比较底层,我们今天在它的基础上做进一步封装。
<dependency> <groupid>org.apache.commons</groupid> <artifactid>commons-compress</artifactid> <version>1.19</version> </dependency> <dependency> <groupid>log4j</groupid> <artifactid>log4j</artifactid> <version>1.2.17</version> </dependency>
工具类
其实,在通常情况下,我们都是在磁盘上进行压缩和解压操作的,这样虽然增加了操作的复杂度,但是却无形中避免了一些问题。
工具类针对.tar.gz格式提供了compressbytar、decompressbytar、compressbygzip、decompressbygzip四个方法,用于处理.tar.gz格式压缩文件,代码如下:
package com.arhorchin.securitit.compress.gzip; import java.io.bufferedinputstream; import java.io.bufferedoutputstream; import java.io.file; import java.io.fileinputstream; import java.io.fileoutputstream; import java.io.ioexception; import org.apache.commons.compress.archivers.tar.tararchiveentry; import org.apache.commons.compress.archivers.tar.tararchiveinputstream; import org.apache.commons.compress.archivers.tar.tararchiveoutputstream; import org.apache.commons.compress.compressors.gzip.gzipcompressorinputstream; import org.apache.commons.compress.compressors.gzip.gzipcompressoroutputstream; import org.apache.commons.compress.utils.ioutils; import org.apache.log4j.logger; /** * @author securitit. * @note 基于磁盘以gzip算法进行压缩和解压工具类. */ public class gzipdiskutil { /** * logger. */ private static logger logger = logger.getlogger(gzipdiskutil.class); /** * utf-8字符集. */ public static string charset_utf8 = "utf-8"; /** * 使用tar算法进行压缩. * @param sourcefolderpath 待进行压缩的文件夹路径. * @param targettarfilepath 压缩后的tar文件存储目录. * @return 压缩是否成功. * @throws exception 压缩过程中可能发生的异常. */ public static boolean compressbytar(string sourcefolderpath, string targettarfilepath) throws exception { // 变量定义. file sourcefolderfile = null; fileoutputstream targettarfos = null; tararchiveoutputstream targettarttaos = null; tararchiveentry targettartae = null; try { // 压缩变量初始化. sourcefolderfile = new file(sourcefolderpath); targettarfos = new fileoutputstream(new file(targettarfilepath)); targettarttaos = new tararchiveoutputstream(targettarfos); // 将文件添加到zip条目中. for (file file : sourcefolderfile.listfiles()) { try (fileinputstream fis = new fileinputstream(file); bufferedinputstream bis = new bufferedinputstream(fis);) { targettartae = new tararchiveentry(file); targettartae.setname(file.getname()); targettarttaos.putarchiveentry(targettartae); targettarttaos.write(ioutils.tobytearray(bis)); targettarttaos.closearchiveentry(); } } } catch (exception ex) { logger.info("gzipdiskutil.compressbytar.", ex); return false; } finally { if (targettarttaos != null) targettarttaos.close(); if (targettarfos != null) targettarfos.close(); } return true; } /** * 使用tar算法进行解压. * @param sourcetarpath 待解压文件路径. * @param targetfolderpath 解压后文件夹目录. * @return 解压是否成功. * @throws exception 解压过程中可能发生的异常. */ public static boolean decompressbytar(string sourcetarpath, string targetfolderpath) throws exception { // 变量定义. fileinputstream sourcetarfis = null; tararchiveinputstream sourcetartais = null; tararchiveentry sourcetartae = null; file singleentryfile = null; try { // 解压定义初始化. sourcetarfis = new fileinputstream(new file(sourcetarpath)); sourcetartais = new tararchiveinputstream(sourcetarfis); // 条目解压缩至指定文件夹目录下. while ((sourcetartae = sourcetartais.getnexttarentry()) != null) { singleentryfile = new file(targetfolderpath + file.separator + sourcetartae.getname()); try (fileoutputstream fos = new fileoutputstream(singleentryfile); bufferedoutputstream bos = new bufferedoutputstream(fos);) { bos.write(ioutils.tobytearray(sourcetartais)); } } } catch (exception ex) { logger.info("gzipdiskutil.decompressbytar.", ex); return false; } finally { if (sourcetartais != null) sourcetartais.close(); if (sourcetarfis != null) sourcetarfis.close(); } return true; } /** * 使用gzip算法进行压缩. * @param sourcefilepath 待进行压缩的文件路径. * @param targetgzipfilepath 压缩后的gzip文件存储目录. * @return 压缩是否成功. * @throws exception 压缩过程中可能发生的异常. */ public static boolean compressbygzip(string sourcefilepath, string targetgzipfilepath) throws ioexception { // 变量定义. fileinputstream sourcefilefis = null; bufferedinputstream sourcefilebis = null; fileoutputstream targetgzipfilefos = null; bufferedoutputstream targetgzipfilebos = null; gzipcompressoroutputstream targetgzipfilegcos = null; try { // 压缩变量初始化. sourcefilefis = new fileinputstream(new file(sourcefilepath)); sourcefilebis = new bufferedinputstream(sourcefilefis); targetgzipfilefos = new fileoutputstream(targetgzipfilepath); targetgzipfilebos = new bufferedoutputstream(targetgzipfilefos); targetgzipfilegcos = new gzipcompressoroutputstream(targetgzipfilebos); // 采用commons-compress提供的方式进行压缩. targetgzipfilegcos.write(ioutils.tobytearray(sourcefilebis)); } catch (exception ex) { logger.info("gzipdiskutil.compressbygzip.", ex); return false; } finally { if (targetgzipfilegcos != null) targetgzipfilegcos.close(); if (targetgzipfilebos != null) targetgzipfilebos.close(); if (targetgzipfilefos != null) targetgzipfilefos.close(); if (sourcefilebis != null) sourcefilebis.close(); if (sourcefilefis != null) sourcefilefis.close(); } return true; } /** * 使用gzip算法进行解压. * @param sourcegzipfilepath 待解压文件路径. * @param targetfilepath 解压后文件路径. * @return 解压是否成功. * @throws @throws exception 解压过程中可能发生的异常. */ public static boolean decompressbygzip(string sourcegzipfilepath, string targetfilepath) throws ioexception { // 变量定义. fileinputstream sourcegzipfilefis = null; bufferedinputstream sourcegzipfilebis = null; fileoutputstream targetfilefos = null; gzipcompressorinputstream sourcegzipfilegcis = null; try { // 解压变量初始化. sourcegzipfilefis = new fileinputstream(new file(sourcegzipfilepath)); sourcegzipfilebis = new bufferedinputstream(sourcegzipfilefis); sourcegzipfilegcis = new gzipcompressorinputstream(sourcegzipfilebis); targetfilefos = new fileoutputstream(new file(targetfilepath)); // 采用commons-compress提供的方式进行解压. targetfilefos.write(ioutils.tobytearray(sourcegzipfilegcis)); } catch (exception ex) { logger.info("gzipdiskutil.decompressbygzip.", ex); return false; } finally { if (sourcegzipfilegcis != null) sourcegzipfilegcis.close(); if (sourcegzipfilebis != null) sourcegzipfilebis.close(); if (sourcegzipfilefis != null) sourcegzipfilefis.close(); if (targetfilefos != null) targetfilefos.close(); } return true; } }
工具类测试
在maven依赖引入正确的情况下,复制上面的代码到项目中,修改package,可以直接使用,下面我们对工具类进行简单测试。测试类代码如下:
package com.arhorchin.securitit.compress.gzip; import com.arhorchin.securitit.compress.gzip.gzipdiskutil; /** * @author securitit. * @note gzipdiskutil工具类测试. */ public class gzipdiskutiltester { public static void main(string[] args) throws exception { gzipdiskutil.compressbytar("c:/users/administrator/downloads/个人文件/2020-07-13/files", "c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar"); gzipdiskutil.compressbygzip("c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar", "c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar.gz"); gzipdiskutil.decompressbygzip("c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar.gz", "c:/users/administrator/downloads/个人文件/2020-07-13/disk-untar.tar"); gzipdiskutil.decompressbytar("c:/users/administrator/downloads/个人文件/2020-07-13/disk-untar.tar", "c:/users/administrator/downloads/个人文件/2020-07-13/disk-untar"); } }
运行测试后,通过查看disk.tar、disk.tar.gz、disk-untar.tar和解压的目录,可以确认工具类运行结果无误。
总结
1) 在小文件、文件数量较小且较为固定时,提倡使用内存压缩和解压方式。使用内存换时间,减少频繁的磁盘操作。《java gzip 基于内存实现压缩和解压》
2) 在大文件、文件数量较大时,提倡使用磁盘压缩和解压方式。过大文件对服务会造成过度的负载,磁盘压缩和解压可以缓解这种压力。
上一篇: 网站排名不好不等于没有利润
下一篇: 网络创业经验 失败的创业经历