如何从错误的编码中恢复文本?

时间:2009-10-14 06:39:35

标签: encoding character-encoding

我有一些亚洲操作系统创建的文件(中文和日文XP) 文件名是乱码,例如:

  

DAE +¾«Ñ¡Õä²ØºÏ¼

我如何恢复原文? 我在c#

中试过这个
Encoding unicode = Encoding.Unicode;
Encoding cinese = Encoding.GetEncoding(936);
byte[] chineseBytes = chinese.GetBytes(garbledString);
byte[] unicodeBytes = Encoding.Convert(unicode, chinese, chineseBytes);
//(Then convert byte in string)

并尝试将unicode更改为windows-1252,但没有运气

4 个答案:

答案 0 :(得分:4)

这是一个双重编码的文本。原始版本在Windows-936中,然后某些应用程序假定文本在ISO-8869-1中并将结果编码为UTF-8。以下是如何在Python中解码它的示例:

>>> print 'иè+¾«Ñ¡Õä²ØºÏ¼­'.decode('utf8').encode('latin1').decode('cp936')
新歌+精选珍藏合辑

我相信你可以在C#中做类似的事情。

答案 1 :(得分:2)

Encoding unicode = Encoding.Unicode;

这不是你想要的。对于真正的UTF-16LE编码,“Unicode”是微软完全误导的名称。 UTF-16LE在这里不起作用,你所拥有的是一个简单的情况,其中936字符串被误译为1252。

Windows代码页1252与ISO-8859-1类似但不相同。没有办法分辨示例字符串中的哪个,因为它不包含两个编码中不同的任何字节0x80-0x9F,但我假设1252,因为这是西方Windows安装的标准代码页。 / p>

Encoding latin= Encoding.getEncoding(1252);
Encoding chinese= Encoding.getEncoding(936);

chinese.getChars(latin.getBytes(s));

答案 2 :(得分:0)

Encoding.Convert的第一个参数是 source 编码,在您的情况下,不应该是chinese吗?所以

Encoding.Convert(chinese, unicode, chineseBytes);

可能确实有效。因为,毕竟,您希望将CP-936 转换为 Unicode,而不是相反。我建议你甚至不要尝试使用CP-1252,因为你的文字非常可能不是拉丁文。

答案 3 :(得分:0)

这是一个老问题,但我在尝试从旧的 Windows Server 2008 R2 服务器迁移 WordPress 上传文件时遇到了同样的情况。 bobince 的回答让我走上了正确的道路,但我不得不寻找正确的编码/解码对。

使用以下 C#,我找到了相关的编码/决定对:

using System;
using System.Text;

public class Program
{
    public static void Main()
    {
        // garbled
        string s = "2020竹慶本樂ä»æ³¢åˆ‡äºžæ´²æ³•ç­µ-Intro-2-1024x643.jpg";
        // expected
        string t = "2020竹慶本樂仁波切亞洲法筵-Intro-2-1024x643.jpg";

        foreach( EncodingInfo ei in Encoding.GetEncodings() )  {
            Encoding e = ei.GetEncoding();
            foreach( EncodingInfo ei2 in Encoding.GetEncodings() )  {
                Encoding e2 = ei2.GetEncoding();
                var s2 = e2.GetString(e.GetBytes(s));
                if (s2 == t) {
                    var x = ei.CodePage;
                    Console.WriteLine($"e1={ei.DisplayName} (CP {ei.CodePage}), e2={ei2.DisplayName} (CP {ei2.CodePage})");
                    Console.WriteLine(t);
                    Console.WriteLine(s2);
                }
            }
        }
        
        Console.WriteLine("-----------");
        Console.WriteLine(t);
        Console.WriteLine(Encoding.GetEncoding(65001).GetString(Encoding.GetEncoding(1252).GetBytes(s)));
    }
}

事实证明,在我的情况下,正确的编码/决定是:

e1=Western European (Windows) (CP 1252), e2=Unicode (UTF-8) (CP 65001)

所以最后一行代码是正确转换 Console.WriteLine(Encoding.GetEncoding(65001).GetString(Encoding.GetEncoding(1252).GetBytes(s))); 的单行代码。