首页 > 解决方案 > ZipFile ExtractToDirectory 错误的文件夹名称 Unicode

问题描述

我有 zip 存档,里面有文件夹。文件夹名称包含 unicode 字符(格鲁吉亚字母)。当我提取它时,我得到了错误的文件夹名称。例如

存档中的文件夹名称:6001 SAHIN INOX 192MM სახელური

提取的文件夹名称:6001 SAHIN INOX 192MM fossyhew

创建存档的机器和我试图提取它的机器是不同的。这是我尝试过的所有不同选项的代码,但没有一个有效。

static void Main(string[] args)
    {
        var ZipFilePath = $"1.zip";
        ZipFile.ExtractToDirectory(ZipFilePath, AppDomain.CurrentDomain.BaseDirectory);
        //ZipFile.ExtractToDirectory(ZipFilePath, AppDomain.CurrentDomain.BaseDirectory, Encoding.UTF8);
        //ZipFile.ExtractToDirectory(ZipFilePath, AppDomain.CurrentDomain.BaseDirectory, new UTF8Encoding());            
        //ZipFile.ExtractToDirectory(ZipFilePath, AppDomain.CurrentDomain.BaseDirectory, Encoding.GetEncoding(1252));
        //ZipFile.ExtractToDirectory(ZipFilePath, AppDomain.CurrentDomain.BaseDirectory, Encoding.GetEncoding(850));            
    }

存档网址:1.zip

项目网址:Project.zip

有任何想法吗?

标签: c#zip

解决方案


我只花了一个小时调试 .NET 源代码,看看发生了什么。

首先要注意的是 ZIP 目录标题中的文件名包含“fossyhew”——这就是值的来源!

调试 fossyhew

如果我们查看目录标题中条目的额外字段,我们可以看到有一个带有标记 0x7075 的条目,其中包含您的 UTF-8 文件名:

调试格鲁吉亚字符

深入规范,0x7075 是“Info-ZIP Unicode Path Extra Field”(参见第 4.6.9 节),它是包含 UTF-8 版本文件名的扩展名:

UnicodeName 是标头中文件名字段内容的 UTF-8 版本。由于 UnicodeName 被定义为 UTF-8,因此不使用 UTF-8 字节顺序标记 (BOM)。该字段的长度是通过从 TSize 中减去先前字段的大小来确定的。如果文件名和注释字段都是 UTF-8,则新的通用位标志位 11(语言编码标志 (EFS))可用于指示标题文件名和注释字段都是 UTF-8 和,在这种情况下,不需要并且不应创建 Unicode 路径和 Unicode 注释额外字段。请注意,为了向后兼容,只有在被压缩的路径和注释的本地字符集已经是 UTF-8 时,才应该使用第 11 位。预计相同的文件名存储方法,无论是通用位 11 还是额外字段,

问题是,ZipArchive不支持从额外字段中读取文件名 - 读取它们的唯一原因是如果您正在更新存档,因此可以将它们写回。ZipArchive但是确实支持通用位 11(它只是用来强制 UTF-8 解码)。

因此,总而言之,有两种方法可以在 ZIP 中设置 UTF-8 文件名:您的存档决定使用的一种方法将文件名指定为代码页 437(这是“fossyhew”的来源)和 UTF-8在一个额外的领域。ZipArchive不支持从这个额外的字段读取。


推荐阅读