我有一个解压功能,我正在使用
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);
}
}
}
}
尝试 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 文件。
首先唯一的官方(不存在......)ZIP格式不允许Unicode字符(那么你不能使用除ASCII以外的任何编码)。
也就是说,许多工具和库允许您使用不同的编码,但它可能会失败(例如,如果您尝试解码 forcing UTF8/UTF32 或使用其他编码编码的任何文件)。
如果文件名以 ASCII 编码,它将获得您系统的代码页:
对于只包含ASCII字符的条目名称,设置语言编码标志,使用当前系统默认代码页对条目名称进行编码。
你对这个主题的 .NET 类没有那么大的控制权。但是,如果您不指定编码,您将获得默认行为(UTF8 用于 ASCII 之外的代码和 ASCII 的当前代码页)。大多数时候它都有效(如果编码和解码都在同一代码页内完成)。
如何避免这种情况?这并不容易(因为我们缺乏标准)但总结一下:
我能给你的最佳提示?依赖默认行为(这很常见),但如果您需要与大多数 ZIP 兼容(因为每个 ZIP 可能以不同的方式实现),则为您的用户提供一种更改它的方法,不仅用于编码,还用于代码页也是。特别是不要用德语特定代码页从代码强制它,因为它会破坏您将处理的第一个西班牙语/法语/意大利语/荷兰语文件(并且没有它们的通用代码页)。
顺便说一句,如果您打开编码错误(不是代码页)的文件,请准备好处理各种异常情况。
为未来的读者编辑(来自评论): CP 850 捕获了大多数常见的西欧字符,但它不是欧洲的代码页。例如,将其与东欧语言或挪威语进行比较。它与它们不匹配(在该语言中,33-127 范围之外的字符非常常见,因为它们不是方框图)。 CP 850 中的某些字符(例如Ê û ı)在(比方说)CP 865(挪威语)中不可用。
让我用一个例子来解释。您有一个文件名(来自 Trukey),名称为:“Garip Dosya Adı.txt”。最后一个字符在 CP 857(土耳其)上的代码为 141。如果您使用的是 CP 850,您将得到 ì 而不是 ı,因为在原始 CP 850 中它的代码为 213。我什至不会提及远东语言(因为固定的代码页甚至会造成混乱如果您仅限于欧洲)。这就是你不能设置固定代码页的原因,除非你正在编写一个小实用程序供自己使用。
我使用了以下库:
using System.IO;
using System.Text;
在以下方法中使用Encoding.Latin1:
File.ReadAllLinesAsync(filePath, Encoding.Latin1, cancellationToken);
在我的案例中有效。
在我的 .net 6 应用程序中,我必须先注册 CodePagesEncodingProvider.Instance,然后使用 850 编码。
string zipPath = @"C:\Users\x\Desktop\zipTest.zip";
string extractPath = @"C:\Users\x\Desktop\test";
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // Register the encoding provider for the appropriate code page
ZipFile.ExtractToDirectory(zipPath, extractPath, System.Text.Encoding.GetEncoding(850));