项目中有压缩导出导入,自身的导出压缩再导入使用ZipInputStream 没有问题,但是有需求对压缩包解压人工干预修改后压缩导入导致解压报错:malformed input off : 0, length : 1
网上查找发现ZipInputStream 解压缩对压缩包内部,若内部节点(文件或目录)名称包含非拉丁文,跨平台传递时,比如压缩方用的utf-8,接收方用的是gbk,Jdk原生库解压流解析就会报错。可以使用ZipArchiveInputStream。
使用ZipArchiveInputStream而非ZipInputStream的原因主要有以下两点:
综上所述,如果需要处理多种压缩格式的文件或者需要更多的选项和功能,建议使用ZipArchiveInputStream。
引入pom依赖:
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-compress</artifactId>
- <version>1.18</version>
- </dependency>
代码实现:
- /**
- * 流zip工具类
- */
- public final classZipUtil {
-
- /**
- * 解压流
- *
- * @param inputStream
- * @return
- */
- @SneakyThrows
- public static InputStream unzipStream(InputStream inputStream) {
- if (inputStream == null) {
- return null;
- }
- //1.Jdk原生Zip流,会因为文件或文件夹命名所用 字符集编码不匹配,报MALFORMED错(畸形的)
- //ZipInputStream zipInputStream = new ZipInputStream(inputStream);
-
- //2.Apach-commons-compress的Zip流,兼容性更好
- ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(inputStream);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- while (zipInputStream.getNextEntry() != null) {
- int n;
- byte[] buff = new byte[1024];
- while ((n = zipInputStream.read(buff)) != -1) {
- bos.write(buff, 0, n);
- }
- }
- bos.flush();
- bos.close();
- return new ByteArrayInputStream(bos.toByteArray());
- }
-
- /**
- * 压缩流
- *
- * @param txtName
- * @param inputStream
- * @return
- */
- public static ByteArrayOutputStream zipStream(String txtName, ByteArrayInputStream inputStream) {
- //Fail-Fast
- if (inputStream == null) {
- return null;
- }
-
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- ZipOutputStream zipOut = new ZipOutputStream(outputStream);
- zipOut.putNextEntry(new ZipEntry(txtName));
-
- int n;
- byte[] buffer = new byte[1024];
- while ((n = inputStream.read(buffer)) != -1) {
- zipOut.write(buffer, 0, n);
- }
-
- zipOut.close();
- inputStream.close();
- outputStream.close();
- return outputStream;
- }
-
- }