【问题标题】:German letters and encoding in C#C# 中的德语字母和编码
【发布时间】:2013-11-28 14:58:19
【问题描述】:

我有解压功能,我使用System.Text.Encoding 来确保解压后的文件保持相同的名称,因为我解压的文件通常包含德语字母。
我尝试了不同的东西,比如 Encoding.Default 或 Encoding.UTF8 但没有任何效果 äÄéöÖüß.txt 被转换为 „Ž‚”™á.txt 或者在默认情况下是黑框:/

有什么建议吗?

using (ZipArchive archive = System.IO.Compression.ZipFile.Open(ZipFile, ZipArchiveMode.Read, System.Text.Encoding.Default))
{

    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        string fullPath = Path.Combine(appPath, entry.FullName);
        if (String.IsNullOrEmpty(entry.Name))
        {
            Directory.CreateDirectory(fullPath);
        }
        else
        {
            if (!entry.Name.Equals("Updater.exe"))
            {
                entry.ExtractToFile(fullPath,true);

            }
        }
    }
}

【问题讨论】:

  • 你也可以试试UTF32
  • 运行时报错“不支持指定的条目名称”
  • 您确定文件名存储正确吗?使用其他解压缩程序会显示哪些名称?
  • 我用的是 7-zip,还有德语字母... :/

标签: c# unicode encoding unzip


【解决方案1】:

首先唯一的官方(不存在...)ZIP格式不允许Unicode字符(那么你不能使用除ASCII以外的任何编码)。

也就是说,许多工具和库允许您使用不同的编码,但它可能会失败(例如,如果您尝试解码 强制 UTF8/UTF32 或任何使用其他编码编码的文件)。

如果文件名以 ASCII 编码,它将获得您系统的代码页:

对于仅包含 ASCII 字符的条目名称,设置语言编码标志,并使用当前系统默认代码页对条目名称进行编码。

对于这个主题,您对 .NET 类没有那么大的控制力。但是,如果您不指定编码,您将获得默认行为(UTF8 用于 ASCII 以外的代码,当前代码页用于 ASCII)。大多数情况下它都有效(如果编码和解码都在同一个代码页中完成)。

如何避免这种情况?这并不容易(因为我们缺乏标准),但总结一下:

  • 不要强制编码(除非您使用的是使用已知编码压缩的 zip 文件)。
  • 在大多数情况下,默认行为都很好。
  • 对于带有扩展字符的 ASCII 编码 ZIP,依赖于系统代码页(在两个系统中必须相同)。
  • 为用户提供更改编码的方法(您无法检查 zip 实用程序使用的编码,并且对此没有标准)。这不仅意味着更改编码(UTF8/UTF16 或其他),还意味着更改代码页(以防它们不匹配)。 GetEncoding 函数将为您提供您指定的代码页的正确编码器)。

我能给你的最好提示是什么?依赖默认行为(这很常见),但如果您需要与大多数 ZIP 兼容,请为您的用户提供一种更改它的方法(因为每个 ZIP 可能以不同的方式实现),不仅用于编码,而且用于代码页也是。特别是不要从代码中强制它使用德语特定的代码页,因为它会与您要处理的第一个西班牙语/法语/意大利语/荷兰语文件中断(并且它们没有通用代码页) .

顺便说一句,如果您打开编码错误的文件(不是代码页),请准备好处理各种异常。

为未来的读者编辑(来自 cmets): CP 850 捕获了大多数常见的西欧字符,但它不是欧洲的代码页。例如,将其与东欧语言或挪威语进行比较。它与它们不匹配(并且在 33-127 范围之外的语言字符非常常见,因为它们不是方框图)。 CP 850 中的某些字符(例如 Ê Ë ı)在(比如说)CP 865(挪威语)中不可用。

让我用一个例子来解释。您有一个具有以下名称的文件名(来自 Trukey):“Garip Dosya Adı.txt”。最后一个字符在 CP 857(土耳其)上的代码为 141。如果您使用的是 CP 850,您将得到 ì 而不是 ı 因为在原始 CP 850 中它的代码为 213。我什至不会提及远东语言(因为即使您仅限于欧洲,固定的代码页也会造成混乱)。这就是您无法设置固定代码页的原因,除非您正在编写一个供自己使用的小实用程序。

【讨论】:

  • 感谢您的解释 :) 非常有用,尤其是我对这个主题知之甚少 :) 再次感谢!
  • 最后一个问题,在我的情况下,代码页 850 有效,但在我的情况下,默认值实际上并没有给我解决方案,继续使用 850 会不会很糟糕?
  • @eMizo 当然这真的很糟糕(除非您正在编写一个供您个人使用的小型实用程序)。页面 850 包含西方语言中使用的大部分 common 字符,但它不是 默认 437 DOS 代码页(理论上遵循 ZIP 格式)。这意味着您可以打开大多数带有德语字符的文件,但它会因完全有效的 ZIP 文件而失败,而且它是 与 Windows 1252 代码页完全不同的事情(许多许多常用字符不匹配)。
  • @eMizo 此外,它仅适用于使用特定 zip 实用程序的计算机中的 ZIP 文件。另一个实用程序可能总是编码 UTF8(例如),它会失败。另一种可能使用 1252 代码页。另一个可能依赖于系统默认和 UTF8(默认框架行为)等等...如果你强制它限制你的实用程序只处理 非常受限的集合他们……
  • Codepage 850 可以在我的机器上完美运行,其中包含从其他(欧洲)国家的其他公司的其他机器收到的 .zip 文件。我没有测试 437,但这主要是因为我不希望在文件名中出现很多画框字符。
【解决方案2】:

尝试 CodePage 850(对我有用):

using (ZipArchive archive = System.IO.Compression.ZipFile.Open(ZipFile, ZipArchiveMode.Read,  System.Text.Encoding.GetEncoding(850)))
{
      // ....

下一条评论来自 Sharpziplib(一个古老的版本),它让我朝着正确的方向前进:

    /* Using the codepage 1252 doesn't solve the 8bit ASCII problem :/
       any help would be appreciated.

      // get encoding for latin characters (like ö, ü, ß or ô)
      static Encoding ecp1252 = Encoding.GetEncoding(1252);
    */

    // private static Encoding _encoding = System.Text.ASCIIEncoding;
    private static Encoding _encoding = System.Text.Encoding.GetEncoding(850);

最后一行是我的更改,使其正确读取带有特殊字符的 zip 文件。

【讨论】:

  • 只有几点说明:第 850 页和第 1252 页是完全不同的东西(绝对不能互换)。强制代码页将破坏与现有 ZIP 文件的兼容性(天知道在哪个国家/地区),甚至与完全有效的 ZIP 文件(使用 default 437 代码页制作)的兼容性。这可能有助于他使用特定的 zip 实用程序打开在他的机器上创建的文件,但它会因为 99% 的其他 ZIP(使用 437、1252 或 UTF8 编码)而失败。
  • SharpZipLib 中提到了 1252,但从未使用过。我用过 850,从其他应用程序读取 zip 文件从来没有遇到任何问题。我从答案的第一句话中删除了对 1252 的引用。
  • CodePage 850 在 WinZip 22.0 64 位上为我工作。谢谢using (ZipArchive archive = ZipFile.Open(Target.FullName, ZipArchiveMode.Update, Encoding.GetEncoding(850)))
【解决方案3】:

我使用了以下库:

using System.IO;
using System.Text;

在以下方法中使用Encoding.Latin1:

File.ReadAllLinesAsync(filePath, Encoding.Latin1, cancellationToken);

这在我的情况下有效。

【讨论】:

    猜你喜欢
    • 2011-10-16
    • 2013-05-17
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 2011-08-18
    • 2019-06-08
    相关资源
    最近更新 更多