2013-02-13 49 views
0

我在編程的Python下面的示例代碼,以及一些confuses.Here的寫入簡單的字符串到一個文件,然後讀回的UnicodeDecodeError與Seek()和read()

>>> 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 

現在的代碼,是什麼讓我感到困惑的是,爲什麼這個UnicodeDecodeError發生在數據字符串是utf8編碼的情況下?手動讀取f.read()可以正常工作,但當使用seek跳轉並讀取(1)時,會顯示此錯誤。

回答

0

在文件內尋找會將讀指針移動字節,而不是字符。調用.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的數據尋求,或以二進制方式打開該文件,並手動解碼。

+0

我的問題是,我認爲read()實際上讀取一個字節不是字符,您的解釋是有道理的。謝謝! – Zed 2013-02-13 17:14:15