You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中波斯语文件名压缩为Zip后显示问号的问题求助

解决Java压缩Zip时波斯语文件名变"?"的问题

我来帮你搞定这个问题——之前处理过不少非ASCII文件名的Zip压缩场景,太清楚这里的坑了!

首先说核心原因:Java标准库的ZipOutputStream默认用的是CP437编码,这是传统Zip格式的老标准,根本不支持波斯语这类非拉丁字符,所以你的文件名里的波斯语字符会被直接替换成"?"。另外你用URLEncoder处理文件名是走偏了——那玩意儿是给URL编码用的,和Zip文件名半毛钱关系都没有,不抛异常才怪呢!

下面给你两个靠谱的解决方案:

方案1:用Java 7+原生API设置UTF-8编码

从Java 7开始,ZipOutputStream新增了setEncoding()方法,直接指定用UTF-8编码文件名就行,不用额外折腾第三方库。

给你写个完整的示例代码,直接就能跑:

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class PersianZipHandler {
    public static void main(String[] args) throws IOException {
        // 你的波斯语文件名
        String sourceFilePath = "تست.txt";
        String outputZipPath = "波斯语文件压缩包.zip";

        // 用try-with-resources自动关闭流,避免资源泄漏
        try (FileOutputStream fos = new FileOutputStream(outputZipPath);
             ZipOutputStream zipOut = new ZipOutputStream(fos)) {

            // 关键!设置Zip使用UTF-8编码文件名
            zipOut.setEncoding("UTF-8");

            File targetFile = new File(sourceFilePath);
            try (FileInputStream fis = new FileInputStream(targetFile)) {
                ZipEntry zipEntry = new ZipEntry(targetFile.getName());
                zipOut.putNextEntry(zipEntry);

                // 读写文件内容
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    zipOut.write(buffer, 0, bytesRead);
                }
                zipOut.closeEntry();
            }
        }
    }
}

方案2:用Apache Commons Compress库(更稳定兼容)

如果你的项目可以引入第三方库,我更推荐用Apache Commons Compress——它对Zip格式的支持比原生API更全面,尤其是处理非ASCII文件名时兼容性更好,还支持Zip64这类扩展格式。

首先在Maven里加依赖(Gradle的话对应调整就行):

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.24.0</version>
</dependency>

然后是示例代码:

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

import java.io.*;

public class CommonsCompressZipDemo {
    public static void main(String[] args) throws IOException {
        String sourceFilePath = "تست.txt";
        String outputZipPath = "commons-波斯语压缩包.zip";

        try (FileOutputStream fos = new FileOutputStream(outputZipPath);
             ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(fos)) {

            // 显式开启UTF-8文件名支持,确保兼容性
            zipOut.setUseLanguageEncodingFlag(true);
            zipOut.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NOT_ENCODEABLE);

            File targetFile = new File(sourceFilePath);
            ZipArchiveEntry entry = new ZipArchiveEntry(targetFile, targetFile.getName());
            zipOut.putArchiveEntry(entry);

            try (FileInputStream fis = new FileInputStream(targetFile)) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    zipOut.write(buffer, 0, bytesRead);
                }
            }
            zipOut.closeArchiveEntry();
        }
    }
}

最后再强调下:别用URLEncoder处理Zip文件名!那是用来转URL参数的,比如把空格转成%20,和Zip文件名编码完全不是一回事,用它只会添乱,导致异常。

内容的提问来源于stack exchange,提问作者Amir Amiri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:04:42