【问题标题】:How to recover string with broken charset to unicode?如何将带有损坏字符集的字符串恢复为 unicode?
【发布时间】:2014-11-26 12:24:23
【问题描述】:

我有一个字符串(实际上是文件名),例如:ноÑÑажнаÑ。它是损坏的联想 NAS 和 samba 配置的遗产。

enca 报告: 通用转换格式 8 位; UTF-8 从 ISO-8859-5 双重编码为​​ UTF-8

如何使用 perl/shell/python 恢复字符串(文件名)?

【问题讨论】:

  • 您给我们的字符串已经无法修复。但是你会从 UTF-8 解码,编码到 Latin-1,从 UTF-8 解码,编码到 ISO-8850-5。你有我们的原始字符串吗?
  • 我可以到达но??ажна?.,它几乎在那里,但问号表示缺少/损坏的 UTF-8 字节序列。
  • 我可以从文件系统读取文件名,但是有:UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 0: unexpected end of data

标签: python perl encoding utf-8 character-encoding


【解决方案1】:

您必须颠倒这个过程。在 Python 中,您可以将 Unicode 值编码为 Latin-1 以再次获得一对一的字节,因此该过程将是:

  • 从 UTF-8 解码为 Unicode
  • 从 Unicode 编码为 Latin-1
  • 再次从 UTF-8 解码为 Unicode
  • 编码为 ISO-8859-5

您的错位文本缺少不可打印的字符。如果我忽略损坏的字符,我会得到:

>>> 'ноÑÑажнаÑ.'.decode('utf8').encode('latin1').decode('utf8', 'ignore').encode('iso8859_5')
'\xdd\xde\xd0\xd6\xdd\xd0.'

在编码为 ISO-8858-5 之前打印结果,但用占位符替换损坏的字符:

>>> print 'ноÑÑажнаÑ.'.decode('utf8').encode('latin1').decode('utf8', 'replace')
но��ажна�.

【讨论】:

  • 谢谢。它适用于 50% 的情况,在其他 50% 的情况下我有:UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 0: unexpected end of data
  • @AndriiPetrenko:在这种情况下,您的字符串似乎无法修复。
  • @AndriiPetrenko:你能把这些失败文件的print repr() 输出粘贴过来吗?
  • @AndriiPetrenko: 如果我忽略解码和编码错误 ('ignore' as second argument) I get the value S01E01 (АлNминиеваN NолNга, СноNбоNдN, КонNакNнNе линзN, Хлеб).avi`。你能给我任何关于我们是什么的线索吗?现在不见了?
  • @AndriiPetrenko:原始文件名会有所帮助,因为这将为我们提供线索,了解原始文件中可能缺少哪些值导致此问题。
【解决方案2】:

我有一个非常相似的问题,从enca -L ru broken-file.txt 输出来看:

Universal transformation format 8 bits; UTF-8
  Surrounded by/intermixed with non-text data
  Doubly-encoded to UTF-8 from ISO-8859-5

上面的答案没有解决问题,所以我尝试了以下变体:

def decode(contents):
    u = contents.decode("utf-8")
    d = u.encode("raw_unicode_escape")
    return d.decode("cp1251")

# Can be used like:
decode(open('broken-file.txt', "b").read())

请注意,在我的情况下,enca 提供了错误信息:我将 ISO-8859-5 替换为 Windows-1251,因为前者几乎没有在任何地方使用。另外,使用raw_unicode_escape 代替latin-1,感谢Decoding double encoded utf8 in Python

【讨论】:

    【解决方案3】:

    我不确定此文本是否可挽救,但作为通用答案,有一个名为 ftfy 的出色 Python 包,它试图恢复格式错误的文本并解释其处理过程。

    基本的 CLI 用法如下所示:

    $ echo "ноÑÑажнаÑ" | ftfy
    ноÑÑажнаÑ
    $ echo "ноÑÑажнаÑ" | ftfy -e iso-8859-5
    УТНУТОУ'У'УТАУТЖУТНУТАУ'
    

    我已经成功地将它与其他输入一起使用:

    $ echo 'Juan Cañas' | ftfy
    Juan Cañas
    

    使用 Python API,您可以获得解释并处理它们:

    >>> ftfy.fix_and_explain('Juan Cañas')
    ExplainedText(text='Juan Cañas', explanation=[('encode', 'sloppy-windows-1252'), ('decode', 'utf-8'), ('normalize', 'NFC')])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-18
      • 2020-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 2018-02-19
      相关资源
      最近更新 更多