假设我有一个ASCII文件(叫做'测试.txt')像这样:
A B C D
X Y Z
^ EOF, no CR after the 'Z'...
在Python中,我可以像这样读取最后一个字节(最后一个字符):
^{pr2}$我可以这样截短最后3个字符:
with open('test.txt', 'r') as f:
f.seek(-3, os.SEEK_END)
f.truncate()
现在假设我有第二个文件(名为'测试.utf')用UTF-8编码,具有以下单字节和多字节字符:
A B C D
Ⓐ Ⓑ Ⓒ Ⓓ
Z Ⓩ
我知道如何读取整个文件(使用编解码器):
>>> f=codecs.open('/tmp/test.utf', 'r', 'utf-8')
>>> L=f.readlines()
>>> L
[u'A B C D\n', u'\u24b6 \u24b7 \u24b8 \u24b9\n', u'Z \u24cf']
我想我可以使用collections模块中的deque来获取最后N个字符:
>>> from collections import deque
>>> with codecs.open(fn,'r+', encoding) as f:
... last_3=deque(f.read(),3)
>>> last_3
deque([u'Z', u' ', u'\u24cf'], maxlen=3)
那么,问题是:有没有什么地方可以让我在逻辑上一个字符一个接一个地从UTF-8文件中退一步,而不用把整个文件读入内存中?使用ASCII很容易;只需在文件开头附近查找一个字节。但是在UTF-8中,Ⓩ
是3个字节(E2 93 8F
),而{
回想一下,UTF-8的宽度是可变的——每个字符在1到4个字节之间。除非你从一开始就开始,否则我认为没有办法知道角色的界限是什么。。。在
那不是真的。你可以在UTF-8的任何一块中找到开头:
所以序列中的第一个字节要么以“0”(单字节字符)或“11”(两个或多个字节的第一个)开头。后续字节都以“10”开头。在
看看这个chart on Wikipedia。在
因此,您只需从文件末尾读取几个字节即可确定字符的开始和结束位置。在
你可以这样做,但不能作为个人角色。将文件视为字节。在
每个UTF-8字符由1到4个字节组成。要读取文件的结尾,请读取最后4*n个字节并开始查找字符边界。UTF-8字符的第一个字节具有
0
或11
的顶层模式,中间的所有其他字节都将采用10
模式。只需向后搜索,直到计算出与图案匹配的正确数字。在相关问题 更多 >
编程相关推荐