我有一些文件包含一堆不同类型的二进制数据,我正在编写一个模块来处理这些文件。
除此之外,它还包含以下格式的UTF-8编码字符串:2字节大端 stringLength (我使用struct.unpack()解析)然后是字符串。由于它是UTF-8,字符串的字节长度可能大于 stringLength ,如果字符串包含多字节字符,则读取(stringLength)会变短(更不用说搞乱所有字符串了)文件中的其他数据)。
如何从文件中读取 n UTF-8字符(与 n 字节不同),知道UTF-8的多字节属性?我一直在谷歌搜索半小时,我发现的所有结果要么不相关,要么做出我无法做出的假设。
答案 0 :(得分:5)
给定文件对象和许多字符,您可以使用:
# build a table mapping lead byte to expected follow-byte count
# bytes 00-BF have 0 follow bytes, F5-FF is not legal UTF8
# C0-DF: 1, E0-EF: 2 and F0-F4: 3 follow bytes.
# leave F5-FF set to 0 to minimize reading broken data.
_lead_byte_to_count = []
for i in range(256):
_lead_byte_to_count.append(
1 + (i >= 0xe0) + (i >= 0xf0) if 0xbf < i < 0xf5 else 0)
def readUTF8(f, count):
"""Read `count` UTF-8 bytes from file `f`, return as unicode"""
# Assumes UTF-8 data is valid; leaves it up to the `.decode()` call to validate
res = []
while count:
count -= 1
lead = f.read(1)
res.append(lead)
readcount = _lead_byte_to_count[ord(lead)]
if readcount:
res.append(f.read(readcount))
return (''.join(res)).decode('utf8')
测试结果:
>>> test = StringIO(u'This is a test containing Unicode data: \ua000'.encode('utf8'))
>>> readUTF8(test, 41)
u'This is a test containing Unicode data: \ua000'
答案 1 :(得分:0)
UTF-8中的一个字符可以是1byte,2bytes,3byte3。
如果必须逐字节读取文件,则必须遵循UTF-8编码规则。 http://en.wikipedia.org/wiki/UTF-8
大多数情况下,您只需将编码设置为utf-8,然后读取输入流。
您无需关心已阅读的字节数。