C# 德语字母与C语言编码#

C# 德语字母与C语言编码#,c#,unicode,encoding,unzip,C#,Unicode,Encoding,Unzip,我有一个解压功能,我使用System.Text.Encoding来确保解压后的文件保持相同的名称,因为我解压的文件通常包含德语字母。 我尝试了不同的方法,比如编码.Default或编码.UTF8,但都不起作用 äÄÖÖß.txt转换为Ž™á.txt或在默认情况下为黑匣子:/ 有什么建议吗 using (ZipArchive archive = System.IO.Compression.ZipFile.Open(ZipFile, ZipArchiveMode.Read, System.Text.

我有一个解压功能,我使用
System.Text.Encoding
来确保解压后的文件保持相同的名称,因为我解压的文件通常包含德语字母。
我尝试了不同的方法,比如
编码.Default
编码.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);

            }
        }
    }
}
首先,唯一的官方(不存在的…)ZIP格式不允许使用Unicode字符(然后您不能使用ASCII以外的任何编码)

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

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

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

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

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

  • 不要强制编码(除非您正在使用压缩的压缩文件,然后使用已知编码)
  • 在大多数情况下,默认行为是相当好的
  • 对于带有扩展字符的ASCII编码拉链,依赖于系统代码页(在两个系统中必须相同)
  • 为用户提供一种更改编码的方法(您无法检查zip实用程序使用的编码,并且没有相关标准)。这意味着不仅要更改编码(UTF8/UTF16或其他),还要更改代码页(以防它们不匹配)。函数将为您指定的代码页提供正确的编码器)
我能给你最好的提示吗?依赖默认行为(这很常见),但如果您需要与大多数ZIP兼容(因为每个ZIP可能以不同的方式实现),则为您的用户提供一种更改方法,不仅用于编码,也用于代码页。尤其是不要使用德语特定的代码页从代码中强制执行它,因为它将与您要处理的第一个西班牙语/法语/意大利语/荷兰语文件(并且没有通用的代码页)

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

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

让我举例说明。您有一个名为“Garip Dosya Adı.txt”的文件名(来自Trukey)。最后一个字符在CP857上的代码为141(用于土耳其)。如果您使用的是CP850,您将得到ì而不是ı,因为在最初的CP850中,它的代码是213。我甚至不会提到远东语言(因为一个固定的代码页将使一个混乱,即使你只限于欧洲)。这就是你不能设置固定代码页的原因,除非你正在编写一个供自己使用的小实用程序。

试试代码页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文件。

您也可以尝试
UTF32
运行“指定的条目名不受支持”时出错。您确定文件名存储正确吗?其他解压程序会显示哪些名称?我使用7-zip,德语字母在那里…:/谢谢你的解释:)真的很有用,尤其是我对这个话题了解甚少:)再次感谢!最后一个问题,在我的例子中,代码页850是有效的,但是默认值实际上没有给我解决方案,在我的例子中,继续使用850会不会很糟糕?@eMizo当然它真的很糟糕(除非你写的是一个供个人使用的小实用程序)。第850页包含西方语言中使用的大多数常见字符,但它不是默认的437 DOS代码页(理论上,ZIP格式会遵循)。这意味着您可以使用德语字符打开大多数文件,但如果使用完全有效的ZIP文件,则会失败,这与Windows 1252代码页完全不同(许多常用字符不匹配)。@eMizo此外,它仅适用于您的机器上的ZIP文件和特定的ZIP实用程序。另一个实用程序可能总是编码UTF8(例如),它将失败。另一个可以使用1252代码页。另一个可能依赖于系统默认值和UTF8(默认框架行为)等等…如果您强制它,您将限制您的实用程序只处理非常有限的一组它们…Codepage 850在我的机器上可以完美地使用从其他(欧洲)国家的其他公司的其他机器接收到的.zip文件。我还没有测试437,但这主要是因为我不希望在文件名中出现很多方框图字符。强制使用代码页将破坏与现有ZIP文件(上帝知道是在哪个国家制作的)的兼容性,甚至会破坏与完全有效的ZIP文件(使用默认的437代码页制作)的兼容性。这可能有助于他打开机器上制作的文件
    /* 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);