一、引言
無論學習什么程序語言,字符串這種數據類型總是着有非常重要。然而最近在學習python這門語言,想要顯示中文,總是出現各種亂碼。於是在網上查了很多資料,各說紛紜,我也嘗試了許多的方法,有時候可以正常顯示,有時候確實亂碼,讓我摸不着頭腦。於是自己利用python讀寫中文的文本文件來嘗試去摸索python中的中文編碼問題。比較幸運的是,最后能夠正常的讀取出文本里面的中文數據並且顯示,而且還能將中文的結果數據寫入文本文件中。但是本文僅僅只是總結處理中文亂碼問題的小結,並沒有將其編碼的原理弄透。那么,下面就讓我們開始吧。
二、准備工作
1、首先得建立一個文本文件(編碼方式是ascii),文本文件的內容如下:
編號,雨量,站點位置
1,10.2,南京
2,45,北京
3,78,上海
2、給這個文件文件的每一行建立一個數據層也就是建立儲存記錄的類
class Rain: def __init__(self,id,acc,site): self.id=id self.acc=acc self.site=site
三、錯誤及其改正
1、錯誤一
首先需要建立一個py文件去着手寫我們的代碼。創建我的py文件之后我還什么代碼都沒寫,僅僅只是寫了兩行注釋之后,保存一下,就發現下面的Console結果框就出來了錯誤。
代碼截圖如下:
原因分析:
原來Python的源代碼默認的編碼是ascii編碼,而我的源代碼文件中的注釋含有中文,只是ascii編碼所不能表達的字符,固然被python解釋器解釋的時候會出現如下錯誤。
解決方案:
只需要在文件的第一或者第二行,也只能是第一,第二行加上如下代碼 :
#coding:utf-8
這行代碼的意思是,讓解釋器用utf-8的方式去解釋源代碼文件。
2、錯誤二
建立好一個py文件之后就要讀取文本里面的文件,代碼如下:
f=open("raindata.txt","r") f.readline()#第一行是列,可以將文件移到第二行開始處 for line in f: print line
結果出現的結果中文都是亂碼的,如下:
1��10.2���Ͼ�
2��45������
3��78���Ϻ�
原因:
因為txt文本文件中的中文都不是ascii編碼,所以在讀取出來的時候需要讀取出來的字符串經過解碼才能正常顯示。
解決方案:
只需要在讀取的文件后面進行解碼就好了。代碼如下:
f=open("raindata.txt","r") f.readline()#第一行是列,可以將文件移到第二行開始處 for line in f: print line.decode("gb2312")
結果如下:
1,10.2,南京
2,45,北京
3,78,上海
3、錯誤三
將數據正確讀取出來之后就需要把每一行的數據存儲到對象中。代碼如下:
f=open("raindata.txt","r") f.readline()#第一行是列,可以將文件移到第二行開始處 for line in f: lines=line.decode("gb2312").split(",") obj=Rain(lines[0],lines[1],lines[2]) data.append(obj)
結果出現了split(",”)這個方法錯誤,提示說這個方法里面的參數不是中文編碼。如下:
lines=line.decode("gb2312").split(",")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 0: ordinal not in range(128)
原因:
在網上看了這種錯誤的解決方案,說是因為我們的解決方案一種把py的源代碼改為了utf-8的編碼,所以可以解決該文件中所有的中文問題,但是調用的方法如何使其他模塊中的方法,而方法還出現中文的話,就會提示錯誤。
解決方案:
既然知道了原因,那么解決的辦法是,把整個環境的編碼默認編碼方式都改成utf-8就好了。更改的代碼如下:
import sys default_encoding="utf-8" if(default_encoding!=sys.getdefaultencoding()): reload(sys) sys.setdefaultencoding(default_encoding) data =[] f=open("raindata.txt","r") f.readline()#第一行是列,可以將文件移到第二行開始處 for line in f: lines=line.decode("gb2312").split(",") obj=Rain(lines[0],lines[1],lines[2]) data.append(obj)
f.close() print len(data)
這樣就解決了。
4、錯誤四
當把文本文件的編碼方式換成了utf-8之后,上面的代碼就出錯了,錯誤如下:
Traceback (most recent call last):
File "D:\program\Java\PythonOne\src\Test\FileHandle.py", line 24, in <module>
lines=line.decode("gb2312").split(",")
UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 3-4: illegal multibyte sequence
原因:
這是因為本來文件的編碼是utf-8,所以用gb2312的編碼方式去解碼,無疑,那肯定是錯誤。然而前面已經設置了本系統默認的編碼方式就是utf-8,所以只需要將讀出來的文本去掉gb2312的編碼方式就好了。代碼如下:
import sys default_encoding="utf-8" if(default_encoding!=sys.getdefaultencoding()): reload(sys) sys.setdefaultencoding(default_encoding) data =[] f=open("raindata.txt","r") f.readline()#第一行是列,可以將文件移到第二行開始處 for line in f: lines=line.split(",") obj=Rain(lines[0],lines[1],lines[2]) data.append(obj) f.close()
這就解決了文本文件為utf-8的編碼方式了。
5、錯誤五:
完成了讀出文本數據的工作之后,接下就是將讀入的數據寫入文本文件的了。代碼如下:
代碼如下:
f1=open('result.txt','w') for vs in data: f1.write(vs.id+","+vs.acc+","+vs.site) f1.write("\n")
這段寫入數據的代碼的分兩種情況。
1、解釋器的默認編碼是utf-8的,而文本文件的編碼也是utf-8的,直接寫入,寫入到txt的結果不會亂碼。
2、而文本文件的編碼也是ascii的,寫入的時候需要編碼之后再寫入,更改的代碼如下:
f1=open('result.txt','w') for vs in data: f1.write((vs.id+","+vs.acc+","+vs.site).encode("gb2312")) f1.write("\n") fl.close()
到此為止,利用python進行讀寫文件的已經能夠成功的運行的。然而,還補充一點,這是在打印列表中的中文時所照成的問題,並不是亂碼的問題。
6、錯誤6
我們在打印含有中文的列表的時候中文得不到有效的輸出,而是以utf-8的編碼輸出。代碼如下:
strs=['你好','hello'] print strs
產生的結果如下:
['\xe4\xbd\xa0\xe5\xa5\xbd', 'hello']
解決方案:
把該列表一項一項的輸出就沒有問題。代碼如下:
strs=['你好','hello'] print strs[0],sts[1]
結果為:
你好 hello
7、錯誤7
我編寫python的腳本的編輯器為eclipse,在eclipse中的控制台中的輸出結果(中文)是正確編碼的,但是在cmd命令窗口中執行py腳本顯示的確實亂碼。打印代碼如下:
print '等待連接'
然后我在cmd窗口中執行腳本的時輸出的情況如下圖:
出現了亂碼。
解決方案:
要讓這個字符串以utf-8的方式去實現,更改的代碼如下圖:
print u'等待連接'
這下不管是在eclipse的控制台中輸出的,還是cmd命令窗口中輸出都是正常顯示。
四、總結
嘗試過這么多錯誤之后終於正確的將文本的數據讀取,也成功的數據寫入到文本文件中。總結一下就那么幾點。
- 源碼中的編碼方式
- 環境中的默認編碼方式
- 結果文件中的編碼方式
畢竟是初學python,對於上面的解決方案的解釋的原理可能是錯誤的,希望各位大牛在看到錯誤的之后能及時指出來,在此感激不盡。