Java GZip 基于内存实现压缩和解压的方法
GZip是常用的无损压缩算法实现,在Linux中较为常见,像我们在Linux安装软件时,基本都是.tar.gz格式。.tar.gz格式文件需要先对目录内文件进行tar压缩,然后使用GZip进行压缩。
本文针对基于磁盘的压缩和解压进行演示,演示只针对一层目录结构进行,多层目录只需递归操作进行即可。
Maven依赖
org.apache.commons:commons-compress:1.19:此依赖封装了很多压缩算法相关的工具类,提供的API还是相对比较底层,我们今天在它的基础上做进一步封装。
org.apache.commons commons-compress 1.19 log4j log4j 1.2.17
在实际应用中,对应不同需求,可能需要生成若干文件,然后将其压缩。在某些应用中,文件较小、文件数量较少且较为固定,频繁与磁盘操作,会带来不必要的效率影响。
工具类针对.tar.gz格式提供了compressByTar、decompressByTar、compressByGZip、decompressByGZip四个方法,用于处理.tar.gz格式压缩文件,代码如下:
packagecom.arhorchin.securitit.compress.gzip;
importjava.io.ByteArrayInputStream;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.util.HashMap;
importjava.util.Map;
importorg.apache.commons.compress.archivers.tar.TarArchiveEntry;
importorg.apache.commons.compress.archivers.tar.TarArchiveInputStream;
importorg.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
importorg.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
importorg.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
importorg.apache.commons.io.IOUtils;
/**
*@authorSecuritit.
*@note基于内存以ZIP算法进行压缩和解压工具类.
*/
publicclassGZipRamUtil{
/**
*使用TAR算法进行压缩.
*@paramsourceFileBytesMap待压缩文件的Map集合.
*@return压缩后的TAR文件字节数组.
*@throwsException压缩过程中可能发生的异常,若发生异常,则返回的字节数组长度为0.
*/
publicstaticbyte[]compressByTar(MaptarFileBytesMap)throwsException{
//变量定义.
ByteArrayOutputStreamtarBaos=null;
TarArchiveOutputStreamtarTaos=null;
TarArchiveEntrytarTae=null;
try{
//压缩变量初始化.
tarBaos=newByteArrayOutputStream();
tarTaos=newTarArchiveOutputStream(tarBaos);
////将文件添加到TAR条目中.
for(Map.EntryfileEntry:tarFileBytesMap.entrySet()){
tarTae=newTarArchiveEntry(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=newByteArrayOutputStream();
}
}
returntarBaos.toByteArray();
}
/**
*使用TAR算法进行解压.
*@paramsourceZipFileBytesTAR文件字节数组.
*@return解压后的文件Map集合.
*@throwsException解压过程中可能发生的异常,若发生异常,返回Map集合长度为0.
*/
publicstaticMapdecompressByTar(byte[]sourceTarFileBytes)throwsException{
//变量定义.
TarArchiveEntrysourceTarTae=null;
ByteArrayInputStreamsourceTarBais=null;
TarArchiveInputStreamsourceTarTais=null;
MaptargetFilesFolderMap=null;
try{
//解压变量初始化.
targetFilesFolderMap=newHashMap();
sourceTarBais=newByteArrayInputStream(sourceTarFileBytes);
sourceTarTais=newTarArchiveInputStream(sourceTarBais);
//条目解压缩至Map中.
while((sourceTarTae=sourceTarTais.getNextTarEntry())!=null){
targetFilesFolderMap.put(sourceTarTae.getName(),IOUtils.toByteArray(sourceTarTais));
}
}finally{
if(sourceTarTais!=null)
sourceTarTais.close();
}
returntargetFilesFolderMap;
}
/**
*使用GZIP算法进行压缩.
*@paramsourceFileBytesMap待压缩文件的Map集合.
*@return压缩后的GZIP文件字节数组.
*@throwsException压缩过程中可能发生的异常,若发生异常,则返回的字节数组长度为0.
*/
publicstaticbyte[]compressByGZip(byte[]sourceFileBytes)throwsIOException{
//变量定义.
ByteArrayOutputStreamgzipBaos=null;
GzipCompressorOutputStreamgzipGcos=null;
try{
//压缩变量初始化.
gzipBaos=newByteArrayOutputStream();
gzipGcos=newGzipCompressorOutputStream(gzipBaos);
//采用commons-compress提供的方式进行压缩.
gzipGcos.write(sourceFileBytes);
}finally{
if(gzipGcos!=null){
gzipGcos.close();
}
if(null==gzipBaos){
gzipBaos=newByteArrayOutputStream();
}
}
returngzipBaos.toByteArray();
}
/**
*使用GZIP算法进行解压.
*@paramsourceGZipFileBytesGZIP文件字节数组.
*@return解压后的文件Map集合.
*@throwsException解压过程中可能发生的异常,若发生异常,则返回的字节数组长度为0.
*/
publicstaticbyte[]decompressByGZip(byte[]sourceGZipFileBytes)throwsIOException{
//变量定义.
ByteArrayOutputStreamgzipBaos=null;
ByteArrayInputStreamsourceGZipBais=null;
GzipCompressorInputStreamsourceGZipGcis=null;
try{
//解压变量初始化.
gzipBaos=newByteArrayOutputStream();
sourceGZipBais=newByteArrayInputStream(sourceGZipFileBytes);
sourceGZipGcis=newGzipCompressorInputStream(sourceGZipBais);
//采用commons-compress提供的方式进行解压.
gzipBaos.write(IOUtils.toByteArray(sourceGZipGcis));
}finally{
if(sourceGZipGcis!=null)
sourceGZipGcis.close();
}
returngzipBaos.toByteArray();
}
}
在Maven依赖引入正确的情况下,复制上面的代码到项目中,修改package,可以直接使用,下面我们对工具类进行简单测试。测试类代码如下:
packagecom.arhorchin.securitit.compress.gzip;
importjava.io.File;
importjava.util.HashMap;
importjava.util.Map;
importorg.apache.commons.io.FileUtils;
importcom.arhorchin.securitit.compress.gzip.GZipRamUtil;
/**
*@authorSecuritit.
*@noteGZipRamUtil工具类测试.
*/
publicclassGZipRamUtilTester{
publicstaticvoidmain(String[]args)throwsException{
MapfileBytesMap=null;
fileBytesMap=newHashMap();
//设置文件列表.
FiledirFile=newFile("C:/Users/Administrator/Downloads/个人文件/2020-07-13/files");
for(Filefile:dirFile.listFiles()){
fileBytesMap.put(file.getName(),FileUtils.readFileToByteArray(file));
}
byte[]ramBytes=GZipRamUtil.compressByTar(fileBytesMap);
ramBytes=GZipRamUtil.compressByGZip(ramBytes);
FileUtils.writeByteArrayToFile(newFile("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)在大文件、文件数量较大时,提倡使用磁盘压缩和解压方式。过大文件对服务会造成过度的负载,磁盘压缩和解压可以缓解这种压力。《JavaGZip基于磁盘实现压缩和解压》
到此这篇关于JavaGZip基于内存实现压缩和解压的文章就介绍到这了,更多相关JavaGZip实现压缩和解压内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。