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



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

当用户使用 windows 内置工具来压缩文件时,我发现它使用的是 IBM437 enconding,当我们有包含"ø"/"Ø"的文件时,这只会给出一些时髦的结果。我用以下代码修复了这一点:

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内部的编码?

检测编码始终是一项棘手的工作,但 UTF8 对有效序列中应包含的值具有严格的按位规则,并且您可以初始化 UTF8Encoding 对象,当这些序列不正确时,通过引发异常来初始化 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 áíóúñѪº¿⌐¬1/21/4¡«» B0 ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐ C0 └┴┬├─┼╞╟╚╔╩╦╠═╬╧ D0 ╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ E0 αßΓπΣσμτΦΘΩδ∞φε∩ F0 ≡±≥≤⌠⌡÷≈°∙·√ⁿ²■

而在 Windows-1252 中:

80 € 'ƒ"...†‡ˆ‰Š‹Œ ž 90 ''""•–— ̃™š›œ žŸ A0 ¡¢ ¡¢¥¦§ ̈©ª«¬ ® ̄ B0 °±²³'μ¶· ̧¹º»1/41/23/4¿ C0 ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ D0 ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß E0 àáâãäåæçèéêëìíîï F0 ðñòóôõö÷øùúûüýþÿ

其中一些甚至不可打印,所以这使得它更容易一些。

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


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

最新更新