这可能是一个微优化,但我想检查给定字节流在通过我的应用程序时是否是有效的 UTF-8,但我不想保留结果解码代码点。换句话说,如果我要调用 large_string.decode('utf-8'),假设编码成功,我不想保留解码返回的 unicode 字符串,并且不想浪费内存在上面。
有多种方法可以做到这一点,例如一次读取几个字节,尝试decode(),然后附加更多字节直到decode()成功(或者我已经用尽了编码中单个字符的最大字节数)。但是 ISTM 应该可以以一种简单地丢弃解码的 unicode 字符而不必自己滚动的方式使用现有的解码器。但是搜索 stdlib 文档时,什么也没有立即浮现在脑海中。
请您参考如下方法:
您可以使用 codecs module 提供的增量解码器:
utf8_decoder = codecs.getincrementaldecoder('utf8')()
这是一个 IncrementalDecoder() instance .然后,您可以按顺序提供此解码器数据并验证流:
# for each partial chunk of data:
try:
utf8_decoder.decode(chunk)
except UnicodeDecodeError:
# invalid data
解码器返回到目前为止解码的数据(减去部分多字节序列,这些序列在下次解码 block 时保持为状态)。这些较小的字符串创建和丢弃的成本很低,您不会在此处创建大字符串。
您不能提供上述循环部分数据,因为 UTF-8 是一种使用可变字节数的格式;部分块在开始时可能有无效数据。
如果您无法从头开始验证,那么您的第一个 block 可能以最多三个连续字节开始。您可以先删除那些:
first_chunk = b'....'
for _ in range(3):
if first_chunk[0] & 0xc0 == 0x80:
# remove continuation byte
first_chunk = first_chunk[1:]
现在,UTF-8 的结构足够了,因此您还可以使用更多此类二进制测试完全在 Python 代码中验证流,但您根本无法匹配内置解码器的解码速度。
