上游服务读取UTF-8字节流,假设它们是ISO-8859-1,将ISO-8859-1应用于UTF-8编码,并将它们发送给我的服务,标记为UTF-8。
上游服务超出了我的控制范围。他们可能会修复它,但它永远不会被修复。
我知道,我可以通过将UTF-8应用于ISO-8859-1编码来修复编码,然后将字节标记为UTF-8。但如果我的上游解决了他们的问题怎么办?
只有当我发现错误的编码时,才能检测到此问题并修复该编码吗?
我也不确定上游编码是ISO-8859-1。我认为上游是perl,所以编码是有意义的,当我应用ISO-8859-1编码时,我尝试过的每一个示例都是正确的。
当源将e4 9c 94 (✔)发送到我的上游时,我的上游就会向我发送c3 a2 c2 9c c2 94 (-)。
✔作为字节:e4 9c 94e4 9c 94作为latin1字符串:ââ作为字节: c3 a2 c2 9c c2 94我可以使用upstream.encode('ISO-8859-1').force_encoding('UTF-8')修复它,但是一旦上游问题解决了,它就会中断。
发布于 2019-06-27 06:22:16
因为您知道它是如何损坏的,所以您可以尝试通过解码接收到的UTF-8字节,编码到latin1,然后再将其解码为UTF-8来解除它的损坏。只有你的损坏字符串,纯ASCII字符串,或非常不可能的拉丁-1字符串组合将成功解码两次。如果该解码失败,假设上游是固定的,并只是解码一次作为UTF-8.一个纯的ASCII字符串将正确地使用任何方法解码,因此也没有任何问题。有有效的UTF-8编码的序列,可以通过双解码,但它们不太可能发生在正常文本中。
下面是Python中的一个示例(您没有提到一种语言.):
# Assume bytes are latin1, but return encoded UTF-8.
def bad(b):
return b.decode('latin1').encode('utf8')
# Assume bytes are UTF-8, and pass them along.
def good(b):
return b
def decoder(b):
try:
return b.decode('utf8').encode('latin1').decode('utf8')
except UnicodeError:
return b.decode('utf8')
b = '✔'.encode('utf8')
print(decoder(bad(b)))
print(decoder(good(b)))输出:
✔
✔发布于 2019-06-27 06:39:21
裸ISO 8859-1几乎保证是无效的UTF-8.试图解码为ISO 8859-1,然后作为UTF-8,如果这产生无效的字节序列,返回到简单解码为UTF-8,应该适用于这种特殊情况。
更详细地说,UTF-8编码严格限制了哪些非ASCII字符序列是允许的.在ISO-8859-1中,允许的模式是非常不可能的,因为在这种编码中,它们表示类似于Ã这样的序列,后面跟着一个不可打印的控制字符或数学操作符,这在任何有效的文本中都不会出现。
发布于 2021-03-11 09:16:19
基于Mark Tolonen的回答,同样在Python 3中:
def maybe_fix_encoding(utf8_string, possible_codec="cp1252"):
"""Attempts to fix mangled text caused by interpreting UTF8 as cp1252
(or other codec: https://docs.python.org/3/library/codecs.html)"""
try:
return utf8_string.encode(possible_codec).decode('utf8')
except UnicodeError:
return utf8_string>>> maybe_fix_encoding("some normal text and some scandinavian characters æ ø å Æ Ø Å")
'some normal text and some scandinavian characters æ ø å Æ Ø Å'https://stackoverflow.com/questions/56761626
复制相似问题