11

我有一个解压缩功能,我使用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);

            }
        }
    }
}
4

3 回答 3

12

尝试 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 文件。

于 2013-11-15T09:26:10.177 回答
11

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

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

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

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

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

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

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

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

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

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

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

于 2013-11-15T09:20:58.323 回答
1

我使用了以下库:

using System.IO;
using System.Text;

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

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

这在我的情况下有效。

于 2021-10-21T08:16:50.543 回答