zip 中的文件编码(C# / ionic-zip)
Posted
技术标签:
【中文标题】zip 中的文件编码(C# / ionic-zip)【英文标题】:Encoding of files inside a zip (C# / ionic-zip) 【发布时间】:2018-07-04 14:16:08 【问题描述】:我们遇到了 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('¥', 'Ø');
这已经运行了一段时间,一切都很好。
但是,因为总是有一个but,所以我们没有尝试使用mac osx中默认工具压缩的文件。 所以现在我们遇到了一个新问题.. 使用 æ、ø 和 å 时,编码为 UTF-8! 所以如果我知道 zip 压缩在哪里,我就可以让它工作,但是有没有简单的方法来检测或规范化 zip 中的编码?
【问题讨论】:
它不在 zip 对象的属性中的任何位置? 注意,检测编码总是一件棘手的事情,但是 UTF8 有严格的规则,你可以以一种在解码时会抛出异常而失败的方式初始化一个 UTF8Encoding 对象失败,所以如果你对 zip 中的所有文件名运行它,它可以相当准确地检测名称 not 是 UTF-8。 感谢@Nyerguds 在您发表评论后我找到了this,它描述了我如何尝试确定字符串的编码.. 如果你愿意,你可以把你的评论写成答案,这样我就可以把它标记为已回答.. 完成,并添加了一些额外内容。不过,我确实希望你能可靠地获得这些文件名的原始字节表示。 【参考方案1】:检测编码总是一件棘手的事情,但是UTF8has strict bitwise rules about what values are expected in a valid sequence,你可以初始化一个UTF8Encoding对象in a way that will fail by throwing an exception when these sequences are incorrect:
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。如果您确定了这些区域,您可以创建一个扫描机制来评估它似乎倾向于哪种编码,只需计算有多少落在每个区域的预期范围之内和之外。
请注意,c# 中的Char
表示一个 unicode 字符,无论它是从什么字节加载的,并且 unicode 字符具有某些分类,您可以通过编程方式查找它们以区分普通字母(可能带有变音符号)和各种类特殊字符(简单示例:我知道这些类之一是“空白字符”)。可能值得研究该系统以自动化确定“正常语言字符”是什么的过程。
【讨论】:
以上是关于zip 中的文件编码(C# / ionic-zip)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中的 WinRAR、7Zip、Zip、Tar、Winzip 中检查文件是不是存在