我在编程Python中遵循示例代码,并且有些混淆。这是将简单字符串写入文件然后将其读回的代码
>>> data = 'sp\xe4m' # data to your script
>>> data, len(data) # 4 unicode chars, 1 nonascii
('späm', 4)
>>> data.encode('utf8'), len(data.encode('utf8')) # bytes written to file
(b'sp\xc3\xa4m', 5)
>>> f = open('test', mode='w+', encoding='utf8') # use text mode, encoded
>>> f.write(data)
>>> f.flush()
>>> f.seek(0); f.read(1) # ascii bytes work
's'
>>> f.seek(2); f.read(1) # as does 2-byte nonascii
'ä'
>>> data[3] # but offset 3 is not 'm' !
'm'
>>> f.seek(3); f.read(1)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa4 in position 0:
unexpected code byte
现在,令我困惑的是,如果数据字符串是utf8编码的话,为什么会发生UnicodeDecodeError?使用手动f.read()读取工作正常,但使用seek跳转和读取(1)时,会出现此错误。
答案 0 :(得分:0)
在文件中查找会将读指针移动 bytes ,而不是字符。 .read()
调用期望能够读取整个字符。因为UTF-8对ASCII字符集之外的任何unicode代码点使用多个字节,所以不能只是寻找多字节UTF-8代码点的中间位置并期望.read()
能够工作。
U + 00a4代码点(字形ä
)被编码为两个字节,C3和A4。在文件中,这意味着现在有5个字节,表示s
,p
,十六进制字节C3和A4,然后是m
。
通过寻找位置3,您将文件头移动到A4字节,然后调用.read()
失败,因为没有前面的C3字节,没有足够的上下文来解码字符。这提高了UnicodeDecodeError
; A4字节是意外的,因为它不是有效的UTF-8序列。
寻找位置4:
>>> f.seek(3); f.read(1)
'm'
更好的是,不要寻找UTF-8数据,或者以二进制模式打开文件并手动解码。