反向解码Unicode文本

7
许多文本编码具有这样的特性,即您可以反向浏览编码文本并仍能解码它。 ASCII、UTF-8、UTF-16和UTF-32都具有此特性。这使您可以轻松地执行一些操作,例如读取文件的最后一行而无需读取其前面的所有行,或者从当前位置向后几行。

不幸的是,Python似乎没有任何方法来反向解码文件。您不能反向读取,也不能在编码文件中按字符数量进行搜索。codecs模块中的解码器支持逐步解码,但不支持反向解码。我找不到任何“UTF-8-backwards”编解码器,我可以将UTF-8字节以相反的顺序输入其中。

我可能可以自己实现基于编解码器的字符边界同步,反向读取二进制块,并将正确对齐的块馈送到codecs模块中的适当解码器中,但这听起来像是一个非专家会错过一些微妙细节并且不会注意到输出错误的事情。

有没有使用现有工具以简单方式在Python中将文本反向解码的方法?


几个人似乎没有理解“读取整个文件来做这件事是违背初衷的”这一点。顺便澄清一下,这也需要适用于可变长度编码,UTF-8支持是必须的。

可能是使用Python倒序读取文件的重复问题。 - gravity
@gravity:那会读取整个文件。我特意想避免这种情况。 - user2357112
@gravity:这在Unicode下不起作用。 - user2357112
2
P.s. UTF-8边界测试很容易。块的第一个字节不能满足(x & 0xc0) == 0x80 - Robᵩ
如果您只想从文件末尾读取,而不将整个文件加载到内存中,则实现可能很简单:[读取行,例如使用mmap(对于非ASCII基础编码,请替换b'\n'并使用.rfind()以提高速度)](https://dev59.com/jXVC5IYBdhLWcg3w9GHM#6813975)并在每行上调用`line.decode(encoding)`。 - jfs
显示剩余3条评论
1个回答

5

缺乏通用解决方案,这里提供一种特定于utf-8的解决方案:

def rdecode(it):
    buffer = []
    for ch in it:
        och = ord(ch)
        if not (och & 0x80):
            yield ch.decode('utf-8')
        elif not (och & 0x40):
            buffer.append(ch)
        else:
            buffer.append(ch)
            yield ''.join(reversed(buffer)).decode('utf-8')
            buffer = []

utf8 = 'ho math\xc4\x93t\xc4\x93s hon \xc4\x93gap\xc4\x81 ho I\xc4\x93sous'
print utf8.decode('utf8')
for i in rdecode(reversed(utf8)):
    print i,
print ""

结果:

$ python x.py 
ho mathētēs hon ēgapā ho Iēsous
s u o s ē I   o h   ā p a g ē   n o h   s ē t ē h t a m   o h 

这看起来就像我对于“自己实现”的情况所考虑的,尽管它没有你在处理真实文件时想要的分块优化。我猜我不想处理的大部分工作实际上是涉及多个编解码器的支持以及编写一个方便、高效的文件对象,该对象支持向前和向后的read操作以及反向迭代;对于仅仅使用UTF-8编码,解码本身并不太复杂。 - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接