在Python 2.7中,我可以成功将Unicode字符串"abc\udc34xyz"
转换为UTF-8(结果为"abc\xed\xb0\xb4xyz"
)。但是当我将UTF-8字符串传递给例如。 pango_parse_markup()
或g_convert_with_fallback()
,我收到“转换输入中的字节序列无效”等错误。显然GTK / Pango函数检测到字符串中的“不成对的代理”并且(正确地)拒绝它。
Python 3甚至不允许将Unicode字符串转换为UTF-8(错误:“'utf-8'编解码器无法编码位置3中的字符'\ udc34':代理不允许”),但我可以运行"abc\udc34xyz".encode("utf8", "replace")
来获取有效的UTF8字符串,其中单独的代理替换为其他字符。这对我来说很好,但我需要一个Python 2的解决方案。
所以问题是:在Python 2.7中,如何将这个Unicode字符串转换为UTF-8,同时用U + FFFD等替换字符替换单独的代理?最好只使用标准的Python函数和GTK / GLib / G ...函数。
顺便说一下。 Iconv可以将字符串转换为UTF8,但只是删除坏字符而不是用U + FFFD替换它。
答案 0 :(得分:9)
您可以在编码前自行进行替换:
import re
lone = re.compile(
ur'''(?x) # verbose expression (allows comments)
( # begin group
[\ud800-\udbff] # match leading surrogate
(?![\udc00-\udfff]) # but only if not followed by trailing surrogate
) # end group
| # OR
( # begin group
(?<![\ud800-\udbff]) # if not preceded by leading surrogate
[\udc00-\udfff] # match trailing surrogate
) # end group
''')
u = u'abc\ud834\ud82a\udfcdxyz'
print repr(u)
b = lone.sub(ur'\ufffd',u).encode('utf8')
print repr(b)
print repr(b.decode('utf8'))
输出:
u'abc\ud834\U0001abcdxyz'
'abc\xef\xbf\xbd\xf0\x9a\xaf\x8dxyz'
u'abc\ufffd\U0001abcdxyz'
答案 1 :(得分:-1)
以下是解决这个问题的原因:
invalid_string.encode('utf16').decode('utf16', 'replace')
我的理解是代理对是UTF-16的一部分,这就是为什么使用UTF-8进行编码/解码并没有做任何事情。