zip 内的文件编码(C# / ionic-zip)

问题描述 投票:0回答:2

我们遇到了 zip 文件内文件编码的问题。 我们使用 ionic zip 来压缩和解压缩档案。 我们位于丹麦,因此文件名中经常包含 æ、ø 或 å。

当用户使用Windows内置工具来压缩文件时,我发现它使用的是IBM437编码,当我们有带有“ø”/“Ø”的文件时,这只会给出一些奇怪的结果。我用以下代码修复了这个问题:

public static string IBM437Encode(this string text)
{
    return text.Replace('ø', '¢').Replace('Ø', '¥');
}
public static string IBM437Decode(this string text)
{
    return text.Replace('¢', 'ø').Replace('¥', 'Ø');
}

这已经运行了一段时间了,一切都很好。

但是,因为总有一个但是,我们没有尝试使用 mac osx 中默认工具压缩的文件。 所以现在我们遇到了一个新问题.. 当使用 æ、ø 和 å 时,编码为 UTF-8! 因此,如果我知道 zip 的压缩位置,我就可以让它工作,但是有没有简单的方法来检测或标准化 zip 内的编码?

c# encoding zip ionic-zip
2个回答
6
投票

检测编码始终是一件棘手的事情,但是 UTF8 对于有效序列中期望的值有严格的按位规则,并且您可以初始化 UTF8Encoding 对象,当这些序列不正确时,该方法将通过抛出异常而失败

public static Boolean MatchesUtf8Encoding(Byte[] bytes)
{
    UTF8Encoding enc = new UTF8Encoding(false, true);
    try { enc.GetString(bytes) }
    catch(ArgumentException) { return false; }
    return true;
}

如果您对 zip 中的所有文件名运行该命令,您可以确定它是否在任何地方失败,在这种情况下您可以得出结论,名称未保存为 UTF-8。


请注意,除了 UTF-8 之外,计算机的默认编码(

Encoding.Default
,在美国和西欧国家通常为 Windows-1252,但根据地区和语言而有所不同)和 DOS-437 编码之间也存在令人烦恼的差异已经遇到了。

区分这些字符非常非常困难,并且可能需要通过实际检查范围超出字节 0x80 的每个编码来完成,这些编码会产生正常的重音字符,以及您通常不会期望在文件名。例如,许多 DOS-437 字符是用于在 DOS 中绘制半图形用户界面的框架。

作为参考,这些是 DOS-437 中的特殊字符(因此字节范围 0x80-0xFF):

80 噗噗噗
90 欧元
A0 áíóúñѪº¿⌐ؽ¼¡«»
B0 ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐
C0 └┴┬├─┼╞╟╚╔╩╦╠═╬╧
D0 ╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀
E0 αßπΣσμτΦθΩδ∞φε∩
F0 ≡±≥≤⌠⌡÷≈°∙·√ⁿ²■

在 Windows-1252 中:

80 €���„...†‡ˆ�Š���� 
第90章
A0  ¡¤£¤¥ªª«Ø�®´
B0°±23´µ¶·¸1°»1/43¿
C0 ÀÁËÆÇÈÉÊËÌÎÎÏ
D0 ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß
E0 àáâãäåæçèéêëìíïïï ¿
F0 ðñòóôõö÷øùúûüýþÿ

其中一些甚至无法打印,因此这使它更容易一些。

如您所见,一般来说,DOS-437 的大部分重音字符都位于 0x80-0xA5 区域(0xE1 处的 Beta 在德国通常用作 eszett),而 Win-1252 几乎所有重音字符都位于该区域0xC0-0xFF。如果您确定了这些区域,您可以创建一个扫描机制来评估它似乎倾向于哪种编码,只需计算每个区域有多少落在预期范围内和之外即可。


请注意,c# 中的

Char
表示 unicode 字符,无论它是从什么字节加载的,并且 unicode 字符具有某些分类,您可以通过编程方式查找这些分类,以区分普通字母(可能带有变音符号)和各种特殊类别字符(简单的例子:我知道这些类别之一是“空白字符”)。可能值得研究该系统来自动确定“正常语言字符”是什么。


0
投票

就我而言,我在使用 IBM437 读取 zip 时遇到了同样的问题。 字符 ¤Øø§ 被错误替换。

使用字符集 IBM850 解决了该问题

© www.soinside.com 2019 - 2024. All rights reserved.