5

我们遇到了 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 内的编码?

4

1 回答 1

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 °±²³´µ¶·¸¹º»¼½¾¿
C0 ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
D0 ÑÒÓÔÕÖ×ØÙÚÛÜÝÞß
E0 àáâãäåæçèéêëììíîï
F0 ðñòóôõö÷øùúûüýþÿ

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

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


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

于 2018-01-26T11:16:28.293 回答