博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
zip4j实现多线程压缩
阅读量:5318 次
发布时间:2019-06-14

本文共 11977 字,大约阅读时间需要 39 分钟。

使用的jar包:zip4j_1.3.2.jar

基本功能:
针对ZIP压缩文件创建、添加、分卷、更新和移除文件
(读写有密码保护的Zip文件)
(支持AES 128/256算法加密)
(支持标准Zip算法加密)
(支持zip64格式)
(支持Store(仅打包,默认不压缩,不过可以手动设置大小)和Deflate压缩方法
(针对分块zip文件创建和抽出文件)
(支持编码)
(进度监控)
压缩方式(3种):
static final int COMP_STORE = 0;(仅打包,不压缩) (对应好压的存储)
static final int COMP_DEFLATE = 8;(默认) (对应好压的标准)
static final int COMP_AES_ENC = 99;

压缩级别有5种:(默认0不压缩)级别跟好压软件是对应的;

static final int DEFLATE_LEVEL_FASTEST = 1;
static final int DEFLATE_LEVEL_FAST = 3;
static final int DEFLATE_LEVEL_NORMAL = 5;
static final int DEFLATE_LEVEL_MAXIMUM = 7;
static final int DEFLATE_LEVEL_ULTRA = 9;
加密方式:
static final int ENC_NO_ENCRYPTION = -1;(默认,没有加密方法,如果采用此字段,会报错”没有提供加密算法”)
static final int ENC_METHOD_STANDARD = 0;
static final int ENC_METHOD_AES = 99;
AES Key Strength:
(默认-1,也就是ENC_NO_ENCRYPTION)
static final int AES_STRENGTH_128 = 0x01;
static final int AES_STRENGTH_192 = 0x02;
static final int AES_STRENGTH_256 = 0x03;

从构造方法可以默认情况:

compressionMethod = Zip4jConstants.COMP_DEFLATE;
encryptFiles = false;//不设密码
readHiddenFiles = true;//可见
encryptionMethod = Zip4jConstants.ENC_NO_ENCRYPTION;//加密方式不加密
aesKeyStrength = -1;//
includeRootFolder = true;//
timeZone = TimeZone.getDefault();//

** * 情景教学压缩操作类 */public class CompressHandler extends Thread {    private Logger logger = Logger.getLogger(CompressHandler.class);    /**     * 存储目录名和对应目录下的文件地址     */    private Map
> resourceMap; /** * 压缩类中的配置文件 */ private String configJson; /** * 配置文件map key为压缩包中的文件名,value为文件内容 */ Map
configJsonMap; /** * 回调接口 */ private ZipOperate zipOperate; /** * 加密标志 */ private boolean encrypt = false; /** * 线程名称 */ private String threadName = Thread.currentThread().getName(); /** * 取消标志 */ private boolean cancelFlag; public CompressHandler() { } public CompressHandler(Map
> resourceMap, Map
configJsonMap, ZipOperate zipOperate) { this(resourceMap, configJsonMap, zipOperate, false); } public CompressHandler(Map
> resourceMap, Map
configJsonMap, ZipOperate zipOperate, boolean encrypt) { this.resourceMap = resourceMap; this.configJsonMap = configJsonMap; this.zipOperate = zipOperate; this.encrypt = encrypt; } public CompressHandler(Map
> resourceMap, String configJson, ZipOperate zipOperate) { this(resourceMap, configJson, zipOperate, false); } public CompressHandler(Map
> resourceMap, String configJson, ZipOperate zipOperate, boolean encrypt) { this.resourceMap = resourceMap; this.configJson = configJson; this.zipOperate = zipOperate; this.encrypt = encrypt; } @Override public void run() { if (zipOperate != null) { zipOperate.beforeCompress(); } String fileName = UUID.randomUUID().toString().replace("-", "").concat(".zip"); String tempDir = SuperdiamondConfig.getConfig(SuperdiamondConfig.SYSTEM_TMMP_FILE_PATH); File tempDirFile = new File(tempDir); if (!tempDirFile.exists()) { tempDirFile.mkdir(); } String filePath = tempDir.concat("/").concat(fileName); //存储生成本地压缩包的文件 List
encryptFileList = new ArrayList<>(); try { ZipFile zipFile = new ZipFile(filePath); logger.info("线程" + threadName + " 开始压缩,压缩的文件名为:" + fileName); long startTime = System.currentTimeMillis(); logger.info("线程" + threadName + " 开始时间为:" + startTime); ZipParameters parameters = new ZipParameters(); //设置压缩方式和压缩级别 parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); //当开启压缩包密码加密时 boolean dirEncrypt = false; if (encrypt || Boolean.parseBoolean(SuperdiamondConfig.getConfig(SuperdiamondConfig.ENABLE_ENCRYPT_ZIP))) { logger.info("线程" + threadName + " 该压缩包需要加密"); addEncryptParameters(parameters); dirEncrypt = true; } for (String dir : resourceMap.keySet()) { logger.info("线程" + threadName + " 添加目录:" + dir); List
resourceInfoList = resourceMap.get(dir); for (ResourceInfo resourceInfo : resourceInfoList) { String resourceFileName = resourceInfo.getFileName(); logger.info("线程" + threadName + " 添加文件:" + resourceFileName); /** * 20180921判断目录名是否为空字符串 true不创建目录 by lizhang10 */ if(StringUtils.isNotEmpty(dir)){ parameters.setFileNameInZip(dir + "/" + resourceFileName); }else{ parameters.setFileNameInZip(resourceFileName); } parameters.setSourceExternalStream(true); InputStream inputStream = resourceInfo.getInputStream(); if (inputStream == null) { //获取文件流 String fileUrl = resourceInfo.getFileUrl(); long startTime1 = System.currentTimeMillis(); logger.info("线程" + threadName + " 开始获取文件流,地址:" + fileUrl + " 开始时间:" + startTime1); inputStream = getInputStream(fileUrl); long endTime1 = System.currentTimeMillis(); logger.info("线程" + threadName + " 结束获取文件流,地址:" + fileUrl + " 结束时间:" + endTime1 + " 耗时毫秒: " + (endTime1 - startTime1)); } //当压缩包没有加密时,则从文件属性中取是否进行加密 if(!dirEncrypt && resourceInfo.isEncrypt()){ //如果是zip的话,则对文件进行解压,然后再加密 if(resourceFileName.endsWith(".zip")){ long saveStartTime = System.currentTimeMillis(); //网络文件路径 String sourceFileName = tempDir.concat("/").concat(UUID.randomUUID().toString().concat(".zip")); logger.info("线程" + threadName + " 该文件["+resourceFileName+"]是zip且需要加密,开始存到本地,路径为:"+sourceFileName+"开始时间:" + saveStartTime); //加密文件路径 String encryptFileName = tempDir.concat("/").concat(UUID.randomUUID().toString().concat(".zip")); File file = new File(sourceFileName); FileOutputStream outputStream = new FileOutputStream(file); byte[] buffer = new byte[8*1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1){ outputStream.write(buffer,0,len); } outputStream.close(); inputStream.close(); long saveEndTime = System.currentTimeMillis(); logger.info("线程" + threadName + " 该文件是zip,存到本地完成,结束时间:" + saveEndTime + " 耗时:"+(saveEndTime - saveStartTime)); long extractStartTime = System.currentTimeMillis(); logger.info("线程" + threadName + " ,开始进行解压加密,开始时间为:" + extractStartTime); ZipFile sourceZipFile = new ZipFile(file); String extractDir = tempDir.concat("/").concat(UUID.randomUUID().toString()); sourceZipFile.extractAll(extractDir); long extractEndTime = System.currentTimeMillis(); ZipFile encryptZipFile = new ZipFile(encryptFileName); ZipParameters parameters2 = new ZipParameters(); //设置压缩方式和压缩级别 parameters2.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); parameters2.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); addEncryptParameters(parameters2); //添加获取文件的文件和目录 File[] fileArray = new File(extractDir).listFiles(); for (File file1 : fileArray) { if(file1.isDirectory()){ encryptZipFile.addFolder(file1,parameters2); } else { encryptZipFile.addFile(file1,parameters2); } } if(!StringUtils.isEmpty(resourceInfo.getConfigJson())){ parameters2.setFileNameInZip("config.json"); parameters2.setSourceExternalStream(true); encryptZipFile.addStream(new ByteArrayInputStream(resourceInfo.getConfigJson().getBytes("utf8")),parameters2); } logger.info("线程" + threadName + " ,完成解压加密,结束时间为:" + extractEndTime + " 耗时: " + (extractEndTime-extractStartTime)); //删除文件 sourceZipFile.getFile().delete(); //删除目录下的文件 deleteFolder(new File(extractDir)); File encryptFile = encryptZipFile.getFile(); inputStream = new FileInputStream(encryptFile); encryptFileList.add(encryptFile); } } //获取需要打包的文件流 zipFile.addStream(inputStream, parameters); inputStream.close(); } } parameters.setSourceExternalStream(true); //如果configJsonMap不为空,且length不为0,则遍历加入到压缩包中 if (configJsonMap != null && configJsonMap.size() > 0) { for (String resourceName : configJsonMap.keySet()) { logger.info("线程" + threadName + " 添加配置文件" + resourceName); parameters.setFileNameInZip(resourceName); String value = configJsonMap.get(resourceName); zipFile.addStream(new ByteArrayInputStream(value.getBytes("utf8")), parameters); } } if (!StringUtils.isEmpty(configJson)) { logger.info("线程" + threadName + " 添加文件config.json"); parameters.setFileNameInZip("config.json"); zipFile.addStream(new ByteArrayInputStream(configJson.getBytes("utf8")), parameters); } logger.info("线程" + threadName + " 压缩文件" + fileName + "完成"); long endTime = System.currentTimeMillis(); logger.info("线程" + threadName + " 结束时间为:" + endTime + " 耗时毫秒:" + (endTime - startTime)); long startTime2 = System.currentTimeMillis(); logger.info("线程" + threadName + " 开始将压缩包上传到文件服务.......开始时间:" + startTime2); FileInfo fileInfo = new CystrageUtil().uploadToRemoteServer(fileName, filePath, null); long endTime2 = System.currentTimeMillis(); logger.info("线程" + threadName + " 上传完成.......结束时间:" + endTime2 + "耗时毫秒: " + (endTime2 - startTime2)); if (cancelFlag){ throw new InterruptedException("线程" + threadName + " 取消压缩"); } //如果传入了后续操作接口,则将文件服务返回的类传入 if (zipOperate != null) { zipOperate.afterCompress(fileInfo, zipFile); zipFile.getFile().delete(); } } catch (Exception e) { logger.error("线程" + threadName + " 文件压缩出错...........文件内容:" + configJson, e); if (zipOperate != null) { zipOperate.errorCompress(); } //删除对应压缩包 new File(filePath).delete(); } finally { try { //关流 inputStream.close(); } catch (IOException e) { inputStream = null; } //删除本地生成的压缩文件 //存储生成本地压缩包的文件 for (File file : encryptFileList) { file.delete(); } } } /** * 删除文件夹下的所有文件 * @param sourceDir */ private void deleteFolder(File sourceDir) { if(sourceDir.isDirectory()){ File[] files = sourceDir.listFiles(); for (File file : files) { deleteFolder(file); } } else { sourceDir.delete(); } sourceDir.delete(); } private void addEncryptParameters(ZipParameters parameters) { String password = SuperdiamondConfig.getConfig(SuperdiamondConfig.ZIP_COMPRESS_PASSWORD); parameters.setEncryptFiles(true); parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); parameters.setPassword(password.toCharArray()); } /** * 获取输入流 * * @param fileUrl * @return */ InputStream inputStream; private InputStream getInputStream(String fileUrl) throws Exception { if(cancelFlag){ throw new InterruptedException("线程" + threadName + " 取消压缩"); } int retry = 1; while (retry <= 3) { try { int index = fileUrl.lastIndexOf("/"); String prefix = fileUrl.substring(0, index + 1); String fileName = fileUrl.substring(index + 1); URL url = new URL(prefix + URLEncoder.encode(fileName, "utf8")); URLConnection connection = url.openConnection(); connection.setDoInput(true); inputStream = connection.getInputStream(); return inputStream; } catch (Exception e) { if (retry == 1) { logger.error("线程" + threadName + " 获取文件出错,文件地址:" + fileUrl, e); } logger.error("开始重试第" + retry + "次"); //由于测试环境服务器承载能力比较差,当获取失败后,睡眠一段时间再重试 if(Boolean.parseBoolean(SuperdiamondConfig.getConfig(SuperdiamondConfig.SYSTEM_TEST_ENVIRONMENT))){ Thread.currentThread().sleep(Long.parseLong(SuperdiamondConfig.getConfig(SuperdiamondConfig.SYSTEM_SLEEP_TIME))); } if (retry == 3) { throw new Exception(e); } retry++; } } return null; } public void setCancelFlag(Boolean cancelFlag){ this.cancelFlag = cancelFlag; } @Override public void interrupt() { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { inputStream = null; logger.info("线程" + threadName + " 关闭io流失败"); } } super.interrupt(); } public static class ResourceInfo { /** * 文件名称 */ private String fileName; /** * 文件地址 */ private String fileUrl; /** * 输入流 */ private InputStream inputStream; /** * 是否要为当前文件添加config,json */ private String configJson; /** * 改文件是否加密 */ private boolean encrypt; public InputStream getInputStream() { return inputStream; } public void setInputStream(InputStream inputStream) { this.inputStream = inputStream; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileUrl() { return fileUrl; } public void setFileUrl(String fileUrl) { this.fileUrl = fileUrl; } public boolean isEncrypt() { return encrypt; } public void setEncrypt(boolean encrypt) { this.encrypt = encrypt; } public String getConfigJson() { return configJson; } public void setConfigJson(String configJson) { this.configJson = configJson; } }}

 

转载于:https://www.cnblogs.com/AnonymouL/p/9700368.html

你可能感兴趣的文章
[Validation] include rules in the domain that may vary from instance to instance
查看>>
IDEA破解 2017 IDEA license server 激活(可用)
查看>>
C# 使用int.TryParse,Convert.ToInt32,(int)将浮点类型转换整数时的区别
查看>>
getElementByClassName()不兼容的解决办法
查看>>
python下sqlite增删查改方法(转)
查看>>
salesforce客户信息打印
查看>>
POJ 2449 Remmarguts' Date
查看>>
Installing OpenCV 2.3.1 in Ubuntu
查看>>
基于netty的微服务架构
查看>>
php+mysql实现数据分批插入
查看>>
炼数成金数据分析课程---16、机器学习中的分类算法(交叉内容,后面要重点看)...
查看>>
js进阶 11-6 jquery如何获取和设置元素的宽高(jquery多方法)
查看>>
如何使用echo.js实现图片的懒加载(整理)
查看>>
php用两个栈来实现队列
查看>>
Bootstrap
查看>>
C#隐藏桌面图标和任务栏
查看>>
第二百四十六节,Bootstrap弹出框和警告框插件
查看>>
第九十五节,移动流体布局和响应式布局总结
查看>>
关系型数据库
查看>>
Log4net数据表
查看>>