Java zip4j setFileNameCharset不工作

Java zip4j setFileNameCharset不工作,java,character-encoding,zipfile,zip4j,Java,Character Encoding,Zipfile,Zip4j,我正在使用zip4j解压文件,但文件名字符集有问题。 这是我的密码 try { ZipFile zipFile = new ZipFile(source); if (zipFile.isEncrypted()) { zipFile.setPassword(password); } System.out.println(System.getProperty("file.encoding"));

我正在使用zip4j解压文件,但文件名字符集有问题。 这是我的密码

 try {
        ZipFile zipFile = new ZipFile(source);
        if (zipFile.isEncrypted()) {
            zipFile.setPassword(password);
        }
        System.out.println(System.getProperty("file.encoding"));
        zipFile.setFileNameCharset("UTF-8");
        zipFile.extractAll(destination);
    } catch (ZipException e) {
        System.out.println(e.getMessage());
    }
}
工作正常,但文件名如下

使用zip4j压缩和解压缩zip文件时,使用相同的字符集


(我的测试用例:压缩UTF-8,提取UTF-8,没问题/zip4j 1.3.2)

如果您想提取由其他软件创建的zip文件。 文件名的字符集可能是系统默认字符集(例如GBK、Shift JIS或其他字符集…)

在这种情况下,如果一个源文件名包含一个unicode字符,而该字符集中不存在该字符。 该ZipEntry中的文件名转换为UTF-8

要提取此类zip文件,必须通过自定义代码逐个转换文件名

ZipFile zipFile = new ZipFile("input.zip");
UnzipParameters param = new UnzipParameters();
zipFile.setFileNameCharset("ISO8859-1");
List list = zipFile.getFileHeaders();
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
    FileHeader fh = (FileHeader) iterator.next();
    byte[] b = fh.getFileName().getBytes("ISO8859-1");
    String fname = null;
    try {
        fname = new String(b, "UTF-8");
        if (fname.getBytes("UTF-8").length != b.length) {
            fname = new String(b,"GBK");//most possible charset 
        }
    } catch (Throwable e) {
        //try other charset or ...
        System.err.println("Invalid file name: "+fname);
    }
    z.extractFile(fh, dir, param, fname);
}

Beck Yang的解决方案确实有效

对于那些用密码加密的方式解压中文命名文件的人。zip4j中有一个bug。在加密和设置密码之前,必须调用setFileNameCharset。否则,输出编码是错误的


而且,只写目录(空目录)也有编码问题。除了修改源代码之外无法修复。

在@Beck Yang的基础上,只需使用
apache tika
库并自动检测字符集,就可以使用任何语言

import org.apache.tika.parser.txt.CharsetDetector;

ZipFile zipFile = new ZipFile("input.zip");
UnzipParameters param = new UnzipParameters();
zipFile.setFileNameCharset("ISO8859-1");
List list = zipFile.getFileHeaders();

for (Iterator iterator = list.iterator(); iterator.hasNext();) {
    FileHeader fh = (FileHeader) iterator.next();
    byte[] b = fh.getFileName().getBytes("ISO8859-1");
    String fname = null;
    try {
        CharsetDetector charDetect = new CharsetDetector();
        charDetect.setText(b);
        String charSet = charDetect.detect().getName();
        fName = new String(b, charSet);
    } catch (Throwable e) {        
        fName = fh.getFileName();
    }
    z.extractFile(fh, dir, param, fname);
}