错误文件名的重新编码
Re-Encoding of wrong filenames
所以我也阅读了 Spolsky Article twice, this question 并尝试了很多。现在我来了。
我在具有 ISO-8859-1 区域设置的 Linux 机器上创建了一个目录结构的 tarball,并使用 7zip 在 Windows 上取消tarred .因此,当我在 Windows Explorer(以及我的 C# 程序中)中查看文件名时,文件名被打乱了:我希望看到德语变音符号 ü
的地方是 ³
- 难怪,因为文件名是使用 ISO-8859-1 代码页写入 tar 文件的,而 Windows 显然不知道这一点。
我想通过将文件重命名为正确的名称来解决此问题。所以我想我必须告诉程序 "read the filename, think of it as ISO-8859-1 and return every character as UTF-16 character."
我找到正确文件名的代码:
void Main()
{
string[] files = Directory.GetFiles(@"C:\test", @"*", SearchOption.AllDirectories);
var e1 = Encoding.GetEncoding("ISO-8859-1");
var e2 = Encoding.GetEncoding("UTF-16");
foreach (var f in files)
{
Console.WriteLine($"Source: {f}");
var source = e1.GetBytes(f);
var dest = Encoding.Convert(e1, e2, source);
Console.WriteLine($"Result: {e2.GetString(dest)}");
}
}
结果 - 什么都没发生:
Source: C:\test\Brief-mrl³.odt
Result: C:\test\Brief-mrl³.odt
预期结果:
Source: C:\test\Brief-mrl³.odt
Result: C:\test\Brief-mrlü.odt
当我交换 e1 和 e2 时,我得到了奇怪的结果。我的脑袋疼。我没有得到什么?
编辑:我知道之前犯了错误,但是现在我在Windows上的文件名有误我需要更正的机器。但是,它可能无法通过 Encoding
-Class 求解。我找到了这个 blog post 并且作者说
It turns out, this isn't a problem with the encoding at all, but the same character address meaning different things to different character sets.
最后,他写了一个方法,用特定的不同字符替换130到173之间的字符。这对我来说看起来并不简单,但这可能是唯一的方法吗?有人可以对此发表评论吗?
经过更多阅读,我自己找到了解决方案。 This excellent article 有帮助。关键是:一旦使用了错误的编码,您只能猜测(或必须知道)究竟出了什么问题。如果你知道,你可以在代码中还原整个事情。
void Main()
{
// We get the source string e.g. reading files from a directory. We see a "³" when
// we expect a German umlaut "ü". The reason can be a poorly configured smb share
// on a Linux server or other problems.
string source = "M³nch";
// We are in a .NET program, so the source string (here in the
// program) is Unicode in UTF-16 encoding. I.e., the codepoints
// M, ³, n, c and h are encoded in UTF-16.
byte[] bytesFromSource = Encoding.Unicode.GetBytes(source); //
// The source encoding is UTF-16, hence we get two bytes per character.
// We accidently worked with the OEM850 Codepage, we now have look up the bytes of
// the codepoints on the OEM850 codepage: We convert our bytesFromSource to the wrong Codepage
byte[] bytesInWrongCodepage = Encoding.Convert(Encoding.Unicode, Encoding.GetEncoding(850), bytesFromSource);
// Here's the trick: Although converting to OEM850, we now assume that the bytes are Codepage ISO-8859-1.
// We convert the bytes from ISO-8859-1 to Unicode.
byte[] bytesFromCorrectCodepage = Encoding.Convert(Encoding.GetEncoding("ISO-8859-1"), Encoding.Unicode, bytesInWrongCodepage);
// And finally we get the right character.
string result = Encoding.Unicode.GetString(bytesFromCorrectCodepage);
Console.WriteLine(result); // Münch
}
警告:不要运行此方法的结果。这可能会产生不可打印的字符或其他混乱。
所以我也阅读了 Spolsky Article twice, this question 并尝试了很多。现在我来了。
我在具有 ISO-8859-1 区域设置的 Linux 机器上创建了一个目录结构的 tarball,并使用 7zip 在 Windows 上取消tarred .因此,当我在 Windows Explorer(以及我的 C# 程序中)中查看文件名时,文件名被打乱了:我希望看到德语变音符号 ü
的地方是 ³
- 难怪,因为文件名是使用 ISO-8859-1 代码页写入 tar 文件的,而 Windows 显然不知道这一点。
我想通过将文件重命名为正确的名称来解决此问题。所以我想我必须告诉程序 "read the filename, think of it as ISO-8859-1 and return every character as UTF-16 character."
我找到正确文件名的代码:
void Main()
{
string[] files = Directory.GetFiles(@"C:\test", @"*", SearchOption.AllDirectories);
var e1 = Encoding.GetEncoding("ISO-8859-1");
var e2 = Encoding.GetEncoding("UTF-16");
foreach (var f in files)
{
Console.WriteLine($"Source: {f}");
var source = e1.GetBytes(f);
var dest = Encoding.Convert(e1, e2, source);
Console.WriteLine($"Result: {e2.GetString(dest)}");
}
}
结果 - 什么都没发生:
Source: C:\test\Brief-mrl³.odt
Result: C:\test\Brief-mrl³.odt
预期结果:
Source: C:\test\Brief-mrl³.odt
Result: C:\test\Brief-mrlü.odt
当我交换 e1 和 e2 时,我得到了奇怪的结果。我的脑袋疼。我没有得到什么?
编辑:我知道之前犯了错误,但是现在我在Windows上的文件名有误我需要更正的机器。但是,它可能无法通过 Encoding
-Class 求解。我找到了这个 blog post 并且作者说
It turns out, this isn't a problem with the encoding at all, but the same character address meaning different things to different character sets.
最后,他写了一个方法,用特定的不同字符替换130到173之间的字符。这对我来说看起来并不简单,但这可能是唯一的方法吗?有人可以对此发表评论吗?
经过更多阅读,我自己找到了解决方案。 This excellent article 有帮助。关键是:一旦使用了错误的编码,您只能猜测(或必须知道)究竟出了什么问题。如果你知道,你可以在代码中还原整个事情。
void Main()
{
// We get the source string e.g. reading files from a directory. We see a "³" when
// we expect a German umlaut "ü". The reason can be a poorly configured smb share
// on a Linux server or other problems.
string source = "M³nch";
// We are in a .NET program, so the source string (here in the
// program) is Unicode in UTF-16 encoding. I.e., the codepoints
// M, ³, n, c and h are encoded in UTF-16.
byte[] bytesFromSource = Encoding.Unicode.GetBytes(source); //
// The source encoding is UTF-16, hence we get two bytes per character.
// We accidently worked with the OEM850 Codepage, we now have look up the bytes of
// the codepoints on the OEM850 codepage: We convert our bytesFromSource to the wrong Codepage
byte[] bytesInWrongCodepage = Encoding.Convert(Encoding.Unicode, Encoding.GetEncoding(850), bytesFromSource);
// Here's the trick: Although converting to OEM850, we now assume that the bytes are Codepage ISO-8859-1.
// We convert the bytes from ISO-8859-1 to Unicode.
byte[] bytesFromCorrectCodepage = Encoding.Convert(Encoding.GetEncoding("ISO-8859-1"), Encoding.Unicode, bytesInWrongCodepage);
// And finally we get the right character.
string result = Encoding.Unicode.GetString(bytesFromCorrectCodepage);
Console.WriteLine(result); // Münch
}
警告:不要运行此方法的结果。这可能会产生不可打印的字符或其他混乱。