Java GZip 实现压缩和解压 Java GZip 基于内存实现压缩和解压的方法
超哥说码 人气:0想了解Java GZip 基于内存实现压缩和解压的方法的相关内容吗,超哥说码在本文为您仔细讲解Java GZip 实现压缩和解压的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Java,GZip,实现压缩和解压,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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; 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.io.IOUtils; /** * @author Securitit. * @note 基于内存以ZIP算法进行压缩和解压工具类. */ public class GZipRamUtil { /** * 使用TAR算法进行压缩. * @param sourceFileBytesMap 待压缩文件的Map集合. * @return 压缩后的TAR文件字节数组. * @throws Exception 压缩过程中可能发生的异常,若发生异常,则返回的字节数组长度为0. */ public static byte[] compressByTar(Map<String, byte[]> tarFileBytesMap) throws Exception { // 变量定义. ByteArrayOutputStream tarBaos = null; TarArchiveOutputStream tarTaos = null; TarArchiveEntry tarTae = null; try { // 压缩变量初始化. tarBaos = new ByteArrayOutputStream(); tarTaos = new TarArchiveOutputStream(tarBaos); // // 将文件添加到TAR条目中. for (Map.Entry<String, byte[]> fileEntry : tarFileBytesMap.entrySet()) { tarTae = new TarArchiveEntry(fileEntry.getKey()); tarTae.setName(fileEntry.getKey()); tarTae.setSize(fileEntry.getValue().length); tarTaos.putArchiveEntry(tarTae); tarTaos.write(fileEntry.getValue()); tarTaos.closeArchiveEntry(); } } finally { if (tarTaos != null) { tarTaos.close(); } if (null == tarBaos) { tarBaos = new ByteArrayOutputStream(); } } return tarBaos.toByteArray(); } /** * 使用TAR算法进行解压. * @param sourceZipFileBytes TAR文件字节数组. * @return 解压后的文件Map集合. * @throws Exception 解压过程中可能发生的异常,若发生异常,返回Map集合长度为0. */ public static Map<String, byte[]> decompressByTar(byte[] sourceTarFileBytes) throws Exception { // 变量定义. TarArchiveEntry sourceTarTae = null; ByteArrayInputStream sourceTarBais = null; TarArchiveInputStream sourceTarTais = null; Map<String, byte[]> targetFilesFolderMap = null; try { // 解压变量初始化. targetFilesFolderMap = new HashMap<String, byte[]>(); sourceTarBais = new ByteArrayInputStream(sourceTarFileBytes); sourceTarTais = new TarArchiveInputStream(sourceTarBais); // 条目解压缩至Map中. while ((sourceTarTae = sourceTarTais.getNextTarEntry()) != null) { targetFilesFolderMap.put(sourceTarTae.getName(), IOUtils.toByteArray(sourceTarTais)); } } finally { if (sourceTarTais != null) sourceTarTais.close(); } return targetFilesFolderMap; } /** * 使用GZIP算法进行压缩. * @param sourceFileBytesMap 待压缩文件的Map集合. * @return 压缩后的GZIP文件字节数组. * @throws Exception 压缩过程中可能发生的异常,若发生异常,则返回的字节数组长度为0. */ public static byte[] compressByGZip(byte[] sourceFileBytes) throws IOException { // 变量定义. ByteArrayOutputStream gzipBaos = null; GzipCompressorOutputStream gzipGcos = null; try { // 压缩变量初始化. gzipBaos = new ByteArrayOutputStream(); gzipGcos = new GzipCompressorOutputStream(gzipBaos); // 采用commons-compress提供的方式进行压缩. gzipGcos.write(sourceFileBytes); } finally { if (gzipGcos != null) { gzipGcos.close(); } if (null == gzipBaos) { gzipBaos = new ByteArrayOutputStream(); } } return gzipBaos.toByteArray(); } /** * 使用GZIP算法进行解压. * @param sourceGZipFileBytes GZIP文件字节数组. * @return 解压后的文件Map集合. * @throws Exception 解压过程中可能发生的异常,若发生异常,则返回的字节数组长度为0. */ public static byte[] decompressByGZip(byte[] sourceGZipFileBytes) throws IOException { // 变量定义. ByteArrayOutputStream gzipBaos = null; ByteArrayInputStream sourceGZipBais = null; GzipCompressorInputStream sourceGZipGcis = null; try { // 解压变量初始化. gzipBaos = new ByteArrayOutputStream(); sourceGZipBais = new ByteArrayInputStream(sourceGZipFileBytes); sourceGZipGcis = new GzipCompressorInputStream(sourceGZipBais); // 采用commons-compress提供的方式进行解压. gzipBaos.write(IOUtils.toByteArray(sourceGZipGcis)); } finally { if (sourceGZipGcis != null) sourceGZipGcis.close(); } return gzipBaos.toByteArray(); } }
工具类测试
在Maven依赖引入正确的情况下,复制上面的代码到项目中,修改package,可以直接使用,下面我们对工具类进行简单测试。测试类代码如下:
package com.arhorchin.securitit.compress.gzip; import java.io.File; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.FileUtils; import com.arhorchin.securitit.compress.gzip.GZipRamUtil; /** * @author Securitit. * @note GZipRamUtil工具类测试. */ public class GZipRamUtilTester { public static void main(String[] args) throws Exception { Map<String, byte[]> fileBytesMap = null; fileBytesMap = new HashMap<String, byte[]>(); // 设置文件列表. File dirFile = new File("C:/Users/Administrator/Downloads/个人文件/2020-07-13/files"); for (File file : dirFile.listFiles()) { fileBytesMap.put(file.getName(), FileUtils.readFileToByteArray(file)); } byte[] ramBytes = GZipRamUtil.compressByTar(fileBytesMap); ramBytes = GZipRamUtil.compressByGZip(ramBytes); FileUtils.writeByteArrayToFile(new File("C:/Users/Administrator/Downloads/个人文件/2020-07-13/ram.tar.gz"), ramBytes); ramBytes = GZipRamUtil.decompressByGZip(ramBytes); fileBytesMap = GZipRamUtil.decompressByTar(ramBytes); System.out.println(fileBytesMap.size()); } }
运行测试后,通过查看ram.tar.gz和控制台输出解压后文件数量,可以确认工具类运行结果无误。
总结
1) 在小文件、文件数量较小且较为固定时,提倡使用内存压缩和解压方式。使用内存换时间,减少频繁的磁盘操作。
2) 在大文件、文件数量较大时,提倡使用磁盘压缩和解压方式。过大文件对服务会造成过度的负载,磁盘压缩和解压可以缓解这种压力。《Java GZip 基于磁盘实现压缩和解压》
加载全部内容