Java原生库解压Zip流报MALFORMED错

  1. 压缩包内部,若内部节点(文件或目录)名称包含非拉丁文,跨平台传递时,比如压缩方用的utf-8,接收方用的是gbk,Jdk原生库解压流解析就会报错,如下:
java.lang.IllegalArgumentException: MALFORMED
	at java.util.zip.ZipCoder.toString(ZipCoder.java:58)
	at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:300)
	at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
  1. 使用Apach-commons-compress能够获得更好的兼容性,只需引入如下依赖:
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-compress</artifactId>
  <version>1.18</version>
</dependency>
  1. 代码修改:
package com.yang.helper;

import lombok.SneakyThrows;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;

/**
 * 流zip工具类
 */
public final class StreamZipUtil {

    /**
     * 解压流
     *
     * @param inputStream
     * @return
     */
    @SneakyThrows
    public static InputStream unzipStream(InputStream inputStream) {
        //Fail-Fast
        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
     */
    @SneakyThrows
    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;
    }

}
posted @ 2022-01-18 18:40  JaxYoun  阅读(3487)  评论(2编辑  收藏  举报