上一篇文章介紹和分析了python2.7中使用print遇到的中文編碼問題的原因和解決方案,本篇主要介紹一下python2.7中執行文件讀寫可能遇到的編碼問題。
1.文件讀取
假如我們讀取一個文件,文件保存時,使用的編碼格式,決定了我們從文件讀取的內容的編碼格式,例如,新建一個文本文件test.txt, 編輯內容,保存的時候注意,編碼格式設定為gb2312,那么使用python讀取文件內容,方式如下:
f = open('test.txt','r') s = f.read() #讀取文件內容,如果是不識別的encoding格式(識別的encoding類型跟使用的系統有關),這里將讀取失敗 '''假設文件保存時以gb2312編碼保存''' u = s.decode('gb2312') #以文件保存格式對內容進行解碼,獲得unicode字符串 '''下面我們就可以對內容進行各種編碼的轉換了''' str = u.encode('utf-8')#轉換為utf-8編碼的字符串str strGbk = u.encode('gbk')#轉換為gbk編碼的字符串str1
注意:1)調用read()函數文件test.txt時,如果test.txt文件中不包含BOM信息(BOM信息一般是3個字節,用於標識文件的編碼格式),則系統會使用現在支持的文件編碼格式(utf-8,gbk等,優先使用utf-8,最后使用系統默認的編碼方式),嘗試着讀取和解析text.txt,如果能打開並解析成功(假設以gbk編碼方式能正確打開test.txt),那么s的編碼類型gbk 。
2)如果open時使用的encoding和文件本身的encoding不一致的話,那么這里將將會產生錯誤
3)s的類型為str
此外,python提供了codecs包,可供進行文件的讀取,包中的open()函數可以指定文件編碼的類型:
import codecs f = codecs.open('text.text','r+',encoding='utf-8')#必須事先知道文件的編碼格式,這里文件編碼是使用的utf-8 content = f.read()#如果open時使用的encoding和文件本身的encoding不一致的話,那么這里將將會產生錯誤 f.write('你想要寫入的信息') f.close()
注意:1)必須事先知道文件的編碼格式,這里文件編碼是使用的utf-8 2)如果open時使用的encoding和文件本身的encoding不一致的話,那么這里將將會產生錯誤
3) content的類型為unicode。
2.文件寫入
調用python文件寫入函數時,如果待寫入變量unStr是unicode類型,則系統首先使用系統的默認編碼方式,將unStr變量進行unicode編碼成str的類型,然后再寫入文件。
unStr=u"測試"
f = open('test.txt','w') f.write(unStr) #如果系統的默認編碼是asii,則會出現UnicodeEncodeError問題
如果系統的默認編碼方式是ascii,則就會出現上文中提到的UnicodeEncodeError問題。解決方法有兩個:
1) 首先獲取文件的默認編碼格式,執行write函數前,將unStr編碼成文件的默認編碼格式,例如:在我的機器上,創建一個新文件時,其文件編碼格式為utf-8,則修改f.write(unStr) 為f.write(unStr.encoding('utf-8'))。(建議選這一種)
2) 修改系統的默認編碼方式為utf-8;
3. 關於sys.setdefaultencoding()和sys.stdout.encoding()
1) sys.setdefaultencoding()是str類型編解碼時默認使用的編碼格式,文件讀寫、str類型編碼,在不明確指定編碼格式的情況下均使用 sys.setdefaultencoding()
#! /usr/bin/env python
# -*- coding: utf-8 -*-
s = '中文字符' # 這里的 str 是 str 類型的,而不是 unicode
s.encode('gb2312')
這句代碼將 s 重新編碼為 gb2312 的格式,即進行 unicode -> str 的轉換。因為 s 本身就是 str 類型的,因此 Python 會自動的先將 s 解碼為 unicode ,然后再編碼成 gb2312。因為解碼是python自動進行的,我們沒有指明解碼方式,python 就會使用 sys.defaultencoding 指明的方式來解碼。很多情況下 sys.defaultencoding為ANSCII,如果 s 不是這個類型就會出錯。
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position
0: ordinal not in range(128)
2)sys.stdout.encoding() 是終端輸出的默認編碼格式,例如:print
至此,python2.7中有關中文編碼的相關問題分析及解決已接近尾聲,由於筆者水平有限,難免出現錯誤和不當的地方,希望大家多多指正。