【记录】使用 ZipInputStream类getNextEntry方法遇到的错误

前文描述:

之前公司有一个 .exe 的工具:A:可以把一个文件放进压缩包,B:可以检验被放进压缩包的文件。

现在需要用Java编写一个类似的工具。


1、工具写好之后进行验证时发现:

1)用java代码工具进行AB操作时完全正常。

2)用java代码工具进行A操作用exe工具进行B操作正常。

3)用exe工具进行A操作,用java工具进行B操作抛出异常。异常如下:

java.util.zip.ZipException: invalid entry size (expected 67324752 but got 5896 bytes)
	at java.util.zip.ZipInputStream.readEnd(Unknown Source)
	at java.util.zip.ZipInputStream.read(Unknown Source)
	at java.util.zip.ZipInputStream.closeEntry(Unknown Source)
	at java.util.zip.ZipInputStream.getNextEntry(Unknown Source)
	at com.iapppay.apk.mark.tool.util.ToolMain.readMark(ToolMain.java:127)
	at com.iapppay.apk.mark.tool.ui.ReadMarkPanel.getMarkFromApk(ReadMarkPanel.java:86)
	at com.iapppay.apk.mark.tool.ui.ReadMarkPanel.actionPerformed(ReadMarkPanel.java:72)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.awt.EventQueue.access$400(Unknown Source)
	at java.awt.EventQueue$3.run(Unknown Source)
	at java.awt.EventQueue$3.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue$4.run(Unknown Source)
	at java.awt.EventQueue$4.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

2、问题详细信息:

exe进行A操作的代码:

//拷贝zip文件
            string tmpZipPath = zipFolder + "\\" + mark + "_" + zipFileName;
            System.IO.File.Copy(zipPath, tmpApkPath, true);


            //将mark对应到文件添加到apk
            using (ICSharpCode.SharpZipLib.Zip.ZipFile zip = new ICSharpCode.SharpZipLib.Zip.ZipFile(tmpZipPath)) 
            {
                zip.BeginUpdate();
                zip.Add(markPath, "META-INF\\" + markEnc);
                zip.CommitUpdate();
                zip.Close();
            }

java工具进行B操作的代码:

ZipInputStream zis = new ZipInputStream(new FileInputStream(file));
		ZipEntry entry = null;
		while((entry = zis.getNextEntry()) != null){
			String entryName = entry.getName();
			if(entryName.contains(ChannelUtil.CHANNEL_DIR+ChannelUtil.MARK_FILE_MARKS)){
				break;
			}
		}
		zis.closeEntry();
		zis.close();

3.解决办法:

java工具进行B操作的代码修改为:

ZipFile zipFile = new ZipFile(file);
		Enumeration<? extends ZipEntry> enumeration= zipFile.entries();
		 
		 while(enumeration.hasMoreElements()){
			String entryName = enumeration.nextElement().getName();
			if(entryName.startsWith(ChannelUtil.CHANNEL_DIR+ChannelUtil.MARK_FILE_MARKS)){
				break;
			}
		 }
		 zipFile.close();






public List<ChannelFundDetailDTO> jdBusinessBillDownLoad(String fundDate, String channelRecordId, AccountConfigModel accountConfigModel, JDPayConfig jdPayConfig) throws ChannelFundLoadException { List<ChannelFundDetailDTO> channelFundDetailDTOList = new ArrayList<>(); String payAccount = accountConfigModel.getPayAccount(); String billDate = DateUtils.convertTime(fundDate, DateFormatEnums.YYYYMMDD, DateFormatEnums.YYYY_MM_DD); String filePath = mallReconProperties.getJdReconLoadUrl() + "/" + payAccount + "/" + billDate + "_bill.zip"; //String filePath = "\\\\PC-PUBYSWL75\\Bill\\JDPAYBILL" + "\\" + payAccount + "\\" + billDate + "_bill.zip"; //String filePath = "E:\\对账文档\\导入\\京东\\萤石02_23_12_交易.xlsx"; logger.info("[流水下载][京东]账号【{}】交易账单文件地址:{}", payAccount, filePath); InputStream inputStream = null; //线上和测试环境可用 try { inputStream = new ByteArrayInputStream(HttpClientPoolUtils.executeResByte(filePath, HttpGet.METHOD_NAME, null, "UTF-8", null, null)); //logger.info("查询抖音账单,返回结果:{}", responseString); } catch (Exception e) { logger.error("[流水下载][京东]账号【{}】获取交易账单http请求出现异常,原因:",payAccount, e); throw new ChannelFundLoadException(MallReconRetCode.LOAD_RECON_DETAIL_ERROR, "获取账单http请求出现异常"); } //读取文件需要白名单,本地适用共享文件 //String path = "\\\\PC-PUBHLW049\\Bill" + "\\" + payAccount + "\\" + billDate + ".zip"; /*try { inputStream = Files.newInputStream(new File(filePath).toPath()); } catch (Exception e) { logger.error("[流水下载][京东]账号【{}】获取账单http请求出现异常,原因:",payAccount, e); throw new ChannelFundLoadException(MallReconRetCode.LOAD_RECON_DETAIL_ERROR.getCode(), "获取账单http请求出现异常"); }*/ //解压zip文件并读取指定文件 Map<String, String> paramsMap = new HashMap<>(); paramsMap.put("fundDate", DateUtils.changeTimes(fundDate, DateFormatEnums.YYYYMMDD, Calendar.DATE, -1)); String businessBillFileName = getContent(jdPayConfig.getBusinessBillFileName(), paramsMap); ZipInputStream zipInputStream; try { zipInputStream = new ZipInputStream(inputStream, Charset.forName("gbk")); ZipEntry zipFile; while ((zipFile = zipInputStream.getNextEntry()) != null) { if (zipFile.isDirectory()) { continue; } String zipFileName = zipFile.getName(); logger.info("[流水下载][京东]zipFileName:{}", zipFileName); if (StringUtils.equals(zipFileName, businessBillFileName)) { inputStream = zipInputStream; break; } } } catch (Exception e) { logger.error("[流水下载][京东]账号【{}】从文件流获取账单文件失败,原因:", payAccount, e); throw new ChannelFundLoadException(MallReconRetCode.CHANNEL_FUND_IMPORT_FAIL, "账单文件获取失败"); } //解析账单 try { List<String[]> jingDongBusinessBillDetailInfoList = CsvReadUtils.readCsvData(inputStream, "gbk", 0); if (jingDongBusinessBillDetailInfoList == null || jingDongBusinessBillDetailInfoList.isEmpty() || jingDongBusinessBillDetailInfoList.size() == 1) { logger.error("[流水下载][京东]账号【{}】交易账单数据为空",payAccount); } else { boolean ishHeader = true; Map<Integer, String> headerMap = new HashMap<>(); for (String[] data : jingDongBusinessBillDetailInfoList) { Map<Integer, String> dataMap = IntStream.range(0, data.length).boxed().collect(Collectors.toMap(j -> j, j -> j == 0 ? data[j].trim().replace("=\"", "").replace("=", "") : data[j].trim().replace("=\"", ""))); if (ishHeader) { headerMap = dataMap; String jdBusinessBillHead = mallReconProperties.getJdBusinessBillRpcHead(); checkHead(jdBusinessBillHead, dataMap); ishHeader = false; continue; } JDPayBusinessBillDetailInfo jdPayBusinessBillDetailInfo = createJDPayBusinessBillDetailInfo(dataMap, headerMap); if (!StringUtils.equals(jdPayBusinessBillDetailInfo.getSettlementStatus(), "结算完成")) { logger.error("[流水下载][京东]账号【{}】交易账单中存在未结算的流水", payAccount); throw new ChannelFundLoadException(MallReconRetCode.CHANNEL_FUND_IMPORT_FAIL, "交易账单中存在未结算的流水"); } ChannelFundDetailDTO channelFundDetailDTO = buildJingDongBusinessBillChannelFundDetail(fundDate, channelRecordId, accountConfigModel, jdPayBusinessBillDetailInfo); channelFundDetailDTOList.add(channelFundDetailDTO); } } } catch (Exception e) { logger.error("[流水下载][京东]账号【{}】账单文件解析失败,原因:", payAccount, e); throw new ChannelFundLoadException(MallReconRetCode.CHANNEL_FUND_IMPORT_FAIL, "账单文件解析失败,请检查文件内容是否符合格式或是否存在交易时间为空"); } return channelFundDetailDTOList; } 这一段代码我要做优化, if (StringUtils.equals(zipFileName, businessBillFileName)) { inputStream = zipInputStream; break; },这里原先是判断有没有和我在配置中心配置的文件名字是否一样,一样的话就直接取当前这个文件;现在我要采用包含来做,例如包含"115122281002"的文件名字的我都要解析,怎么优化呢
08-22
public ByteArrayOutputStream appendToExistingZip( ByteArrayOutputStream originalZipStream, List<AttachmentsVo> newAttachments) throws Exception { // 创建新的输出流存放最终结果 ByteArrayOutputStream finalBaos = new ByteArrayOutputStream(); try (ZipOutputStream zos = new ZipOutputStream(finalBaos); ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(originalZipStream.toByteArray()))) { // 步骤1:复制原始ZIP内容 ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { // 创建相同名称的新条目 zos.putNextEntry(new ZipEntry(entry.getName())); // 复制文件内容 byte[] buffer = new byte[1024 * 1024]; int bytesRead; while ((bytesRead = zis.read(buffer)) != -1) { zos.write(buffer, 0, bytesRead); } zos.closeEntry(); zis.closeEntry(); } // 步骤2:添加新文件(复用原有下载逻辑) RestTemplate restTemplate = new RestTemplate(); for (AttachmentsVo attachment : newAttachments) { String fileUrl = fileIntranetUrl + attachment.getFileId(); ResponseEntity<Resource> response = restTemplate.exchange( fileUrl, HttpMethod.GET, null, Resource.class); if (response.getStatusCode() == HttpStatus.OK) { String fileName = System.currentTimeMillis() + "__" + attachment.getFileName(); try (InputStream is = response.getBody().getInputStream()) { zos.putNextEntry(new ZipEntry(fileName)); byte[] buffer = new byte[1024 * 1024]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { zos.write(buffer, 0, bytesRead); } zos.closeEntry(); } } else { logger.info("追加文件下载失败: " + attachment.getBizId()); } } } return finalBaos; } 这个方法中 如果遇到 originalZipStream 参数是null 没有, 该如何解决保证方法正在压缩新文件
最新发布
09-19
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值