27

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

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

我从诱变剂中提取的原始字符串(假设为 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')

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

4

6 回答 6

32

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

d.decode('cp1251').encode('utf8')
于 2011-09-26T12:53:30.020 回答
5

您的字符串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'
于 2011-09-28T08:01:15.080 回答
4

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

于 2011-09-26T12:55:11.877 回答
2

我宁愿在 Александр Степаненко 答案中添加评论,但我的声誉还不允许这样做。我在将 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')
于 2017-07-22T15:56:52.257 回答
1

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

u'\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-х комнатная квартира с отличным ремонтом....”

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

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

some_file.write(text.encode("cp1251").decode('cp1251').encode('utf8'))
于 2016-10-26T11:57:21.873 回答
0

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

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

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

“编码”意味着它是一个字节流,可以像任何其他数据一样传递,但对于操作或显示没有用。

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

'\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')有这个权利,我只是希望能帮助解释为什么这应该有效。

于 2016-01-07T19:17:09.690 回答