【问题标题】:How to convert a string from CP-1251 to UTF-8?如何将字符串从 CP-1251 转换为 UTF-8?
【发布时间】:2011-11-25 04:50:16
【问题描述】:

我正在使用诱变剂将 ID3 标签数据从 CP-1251/CP-1252 转换为 UTF-8。在 Linux 中没有问题。但在 Windows 上,在 wx.TextCtrl 上调用 SetValue() 会产生错误:

UnicodeDecodeError: 'ascii' 编解码器无法解码位置上的字节 0xc3 0:序数不在范围内(128)

我从mutagen 提取的原始字符串(假设为 CP-1251 编码)是:

u'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'

我已尝试将其转换为 UTF-8:

dd = d.decode('utf-8')

...甚至将默认编码从 ASCII 更改为 UTF-8:

sys.setdefaultencoding('utf-8')

...但是我得到了同样的错误。

【问题讨论】:

  • @sashoalm 抱歉,答案已经参考了示例(代码)。我认为你让问题脱颖而出是对的,但解决整个问题不是你的决定。
  • @sashoalm 废话,当所有答案都提到它时,不要删除代码。
  • 如果最初以这种形式发布,这个问题会很好,但现在要核对它的所有内容已经太晚了。
  • 是的,我试图让答案对来自 Google 搜索的人有用。我记得曾经读过 StackOverflow 应该提供规范的答案。也许我应该在 Meta 上询问我的编辑是否正确。

标签: python utf-8 wxpython cp1251


【解决方案1】:

如果你确定你的输入中有 cp1251,你可以这样做

d.decode('cp1251').encode('utf8')

【讨论】:

  • 为了更准确。我从文件中获取 ID3 标签数据,对其进行转换,并使用 wx.TextCtrl 显示。所以,如果我输入 self.artistafter2.SetValue(self.track['artist'][0].encode('utf-8')) 我有一个错误: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3在位置 0:序数不在范围内(128)
  • 谢谢。我发现问题出在 wx.TextCtrl 组件中。
【解决方案2】:

您的字符串 d 是 Unicode 字符串,不是 UTF-8 编码的字符串!所以你不能decode()它,你必须encode()它到UTF-8或者你需要的任何编码。

>>> d = u'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'
>>> d
u'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'
>>> print d
Áåëàÿ ÿáëûíÿ ãðîìó
>>> a.encode("utf-8")
'\xc3\x81\xc3\xa5\xc3\xab\xc3\xa0\xc3\xbf \xc3\xbf\xc3\xa1\xc3\xab\xc3\xbb\xc3\xad\xc3\xbf \xc3\xa3\xc3\xb0\xc3\xae\xc3\xac\xc3\xb3'

(例如,当您需要将其保存为 UTF-8 编码文件时,您会在所有处理结束时执行此操作)。

如果您的输入采用不同的编码,则相反:

>>> d = "Schoßhündchen"                 # native encoding: cp850
>>> d = "Schoßhündchen".decode("cp850") # decode from Windows codepage
>>> d                                   # into a Unicode string (now work with this!)
u'Scho\xdfh\xfcndchen'
>>> print d                             # it displays correctly if your shell knows the glyphs
Schoßhündchen
>>> d.encode("utf-8")                   # before output, convert to UTF-8
'Scho\xc3\x9fh\xc3\xbcndchen'

【讨论】:

  • 感谢您的回答。真的很有帮助。
【解决方案3】:

如果d 是一个正确的Unicode 字符串,那么d.encode('utf-8') 会产生一个编码的UTF-8 字节串。但是不要通过打印来测试它,它可能只是因为代码页的恶作剧而无法正确显示。

【讨论】:

  • 在 Windows 7、Python 2.7.2 中为我工作。
  • 是的。它也适用于我。我发现问题出在 wx.TextCtrl 组件中。
【解决方案4】:

我宁愿在 Александр Степаненко 答案中添加评论,但我的声誉还不允许这样做。我在将 MP3 标签从 CP-1251 转换为 UTF-8 时遇到了类似的问题,并且编码/解码/编码的解决方案对我有用。除了我不得不用“latin-1”替换第一个编码,它基本上将 Unicode 字符串转换为字节序列而没有真正的编码:

print text.encode("latin-1").decode('cp1251').encode('utf8')

并且为了使用例如诱变剂保存回来,它不需要编码:

audio["title"] = title.encode("latin-1").decode('cp1251')

【讨论】:

    【解决方案5】:

    我浪费了半天的时间来寻找正确的答案。因此,如果您从外部源 windows-1251 编码(在我的情况下来自网站)获得一些 unicode 字符串,您将在 Linux 控制台中看到如下内容:

    你'\u043a\u043e\u043c\u043d\u0430\u0442\u043d\u0430\u044f \u043a\u0432\u0430\u0440\u0442\u0438\u0440\u0430.....'

    这不是您数据的正确 unicode 表示形式。所以,蒂姆·皮茨克是对的。您应该首先对其进行编码()然后解码(),然后再次编码以正确编码。

    所以在我的例子中,这条奇怪的行被保存在“text”变量中,并且行:

    print text.encode("cp1251").decode('cp1251').encode('utf8')   
    

    给了我:

    “Своя 2-х комнатная квартира с отличным ремонтом....”

    是的,这也让我发疯。但它有效!

    附:保存到文件你应该这样做。

    some_file.write(text.encode("cp1251").decode('cp1251').encode('utf8'))
    

    【讨论】:

      【解决方案6】:

      我在此回复中提供了一些有关编码/解码文本的相关信息:https://stackoverflow.com/a/34662963/2957811

      要补充一点,重要的是要考虑两种可能状态之一的文本:“编码”和“解码”

      'decoded' 表示它在解释器/库的内部表示中,可用于字符操作(例如搜索、大小写转换、子字符串切片、字符计数……)或显示(查找代码点字体和绘制字形),但不能传入或传出正在运行的进程。

      'encoded' 表示它是一个字节流,可以像任何其他数据一样传递,但对操作或显示没有用处。

      如果您以前使用过序列化对象,请将“解码”视为内存中有用的对象,将“编码”视为序列化版本。

      '\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3' 是您的编码(或序列化)版本,大概是用 cp1251 编码的。这种编码必须是正确的,因为这是用于序列化字符的“语言”,并且需要在内存中重新创建字符。

      需要将其从当前编码 (cp1251) 解码为 python unicode 字符,然后将其重新编码为 utf8 字节流。建议d.decode('cp1251').encode('utf8') 的回答者有这个权利,我只是希望能帮助解释为什么应该这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-17
        • 1970-01-01
        • 2013-03-02
        • 1970-01-01
        • 2016-07-13
        • 1970-01-01
        • 2013-08-20
        • 2010-09-21
        相关资源
        最近更新 更多