UnicodeDecodeError: 'gbk' codec can't decode byte 0xbf in position 2: illegal multibyte sequence
今天練習通過讀取英文版的Walden.txt的文本信息,統計文本中的英文單詞詞頻的時候出現了這樣的錯誤提示。
錯誤的意思是:Unicode的解碼(Decode)出現錯誤了,以gbk編碼的方式去解碼(該字符串變成Unicode),但是此處通過gbk的方式,卻無法解碼(can't decode).''illegal multibyte sequence"的意思是非法的多字節序列,也就是說無法解碼了。
出現這樣的錯誤,可能是要處理的字符串本身不是gbk編碼,卻是以gbk編碼去解碼。比如,字符串本身是utf-8的,但用gbk去解碼,必然出錯。
針對以上的這個問題,查閱網上資料,可以按照如下的步驟進行嘗試:
(1)在打開文本時候,可以指明打開方式:
file = open(path, encoding='gbk')
(2)如果上一步還不能解決,可能是文本中出現的一些特殊符號超出了gbk的編碼范圍,可以選擇編碼范圍更廣的‘gb18030’,如:
file = open(path, encoding='gb18030')
(3)如果(2)還不能解決,說明文中出現了連‘gb18030'也無法編碼的字符,可以使用‘ignore’屬性忽略非法字符,如:
file = open(path, encoding='gb18030', errors='ignore')
或者:
file=open(path).read().decode(‘gb18030’,’ignore’)
通過嘗試,基本解決問題,源代碼如下:
path = 'E://Python/Walden.txt' file = open(path,encoding = 'gb18030',errors = 'ignore') file2 = open('E://Python/Walden2.txt','w') file2.write(file.read()) file.close() file2.close() with open('E://Python/Walden2.txt','r') as text: words = text.read().split() print(words) for word in words: print('{}-{} times'.format(word,words.count(word)))
結果如圖:
雖然已經能夠區分各個單詞,但還有一定的問題,如大小寫重復統計,字符-的統計,還需要進一步改進。
總結:
Python文件讀寫的幾種模式:
r, rb ,w ,wb 那么在讀寫文件時,有無b標識的主要區別在哪里呢?
1.文件使用方式標識
‘r’: 默認值,表示從文件讀取數據。
‘w’: 表示要向文件寫入數據,並截斷從前的內容
‘a’:表示要向文件寫入數據,添加到當前內容尾部
‘r+’ :表示對文件進行可讀寫操作(刪除以前的所有數據)
‘r+a’:表示對文件可進行讀寫操作(添加到當前文件尾部)
‘b’:表示要讀寫二進制數據
2.讀文件
進行讀文件操作時,直到讀到文檔結束符(EOF)才算讀取到文件最后,Python會認為字節\x1A(26)轉換成的字符為文檔結束符(EOF),故使用‘r’進行讀取二進制文件時,可能會出現文檔讀取不全的現象。
例如:二進制文件中存在如下從低位向高位排列的數據:7F 32 1A 2F 3D 2C 12 2E 76
如果使用‘r’進行讀取,則讀到第三個字節,即認為文件結束。
如果使用‘rb’按照二進制位進行讀取的,不會將讀取的字節轉換成字符,從而避免了上面的錯誤。
解決方案: 二進制文件就用二進制方法讀取‘rb’
總結:
使用‘r’的時候,如果碰到‘0x1A’,就視為文件結束,就是EOF。使用‘rb’則不存在這個問題,即:如果你用二進制寫入再用文件讀出的話,如果其中存在‘0x1A’,就只會讀出文件的一部分,使用‘rb’會一直讀取文件末尾。
3.寫文件
對於字符串x='abc\ndef',我們可用len(x)得到它的長度為7,\n我們稱之為換行符,實際上就是0x0A。當我們用‘w’即文本方式寫的時候,在windows平台上會自動將‘0x0A’變成兩個字符‘0x0D’,'0x0A',即文件長度實際上變成8。當用‘r’文本方式讀取時,又自動的轉換成原來的換行符。如果換成‘wb’二進制方式來寫的話,則會保持一個字符不變,讀取的時候也是原樣讀取。所以如果用文本方式寫入,用二進制方式讀取的話,就要考慮這多出的一個字節了。‘0x0D’也稱回車符。Linux下不會變,因為Linux只使用‘0x0A’來表示換行。