自己經(jīng)常在Linux和Windows下使用各種各樣的軟件,經(jīng)常遇到的亂碼的問(wèn)題。
之前的對(duì)策是google XX軟件 亂碼 得到的結(jié)果往往是這樣子的
Step1... Step2... Step3... ....
于是自己也跟著做,有時(shí)能成功,但有時(shí)依然亂碼,只好放棄使用這個(gè)軟件。
我想我的問(wèn)題一直不知道為什么會(huì)出現(xiàn)亂碼,當(dāng)然,并不是完全不知,說(shuō)起編碼,也能說(shuō)出個(gè)一二三來(lái),什么unicode, utf-8, 轉(zhuǎn)換編碼之類(lèi)的。但自己并沒(méi)有一個(gè)清晰的概念。所以一直出問(wèn)題,也不知道問(wèn)題的根源在哪里。所以出了問(wèn)題,解決問(wèn)題的方式只能上網(wǎng)搜索,純屬碰運(yùn)氣。
直到前一段時(shí)間讀到The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets這篇文章,發(fā)現(xiàn)自己有了那么一點(diǎn)點(diǎn)清晰的概念,之后在學(xué)Python Module of the Week中的編碼時(shí),仔細(xì)思考了一下,總算把亂碼產(chǎn)生的原因想的大概明白了。
其實(shí),說(shuō)起來(lái)很簡(jiǎn)單,對(duì)于文本來(lái)說(shuō),主要有兩種操作
- 將文本寫(xiě)入文件
- 從文件中讀取
其中如果寫(xiě)入文件時(shí)和讀取文件時(shí)使用的編碼不一樣,則可能會(huì)產(chǎn)生亂碼,到這里似乎還很簡(jiǎn)單。
一般情形是這樣子的,使用一個(gè)文件編輯器編輯一個(gè)文件,然后保存,保存的時(shí)候選取某一種編碼,這一過(guò)程對(duì)應(yīng) 1. 寫(xiě)入文件時(shí)的編碼。
讀取文件時(shí),往往使用文本編輯器打開(kāi)一個(gè)文件,如果此時(shí)文本編輯器設(shè)定的編碼方式與文件保存時(shí)使用的編碼方式一樣,那么顯示的時(shí)候就不會(huì)有亂碼,如果不一樣,則可能產(chǎn)生亂碼(如果保存時(shí)使用的編碼是顯示時(shí)設(shè)置的編碼的子集,一般會(huì)正常顯示)。這一過(guò)程對(duì)應(yīng) 2. 從文件中讀取 。
由以上可以看的出來(lái),使用文本編輯器保存時(shí)是寫(xiě)入,使用文本編輯器打開(kāi)文件時(shí)是讀取。這種情況很簡(jiǎn)單。
但是, 寫(xiě)入文件 和 讀取文件 并非只有以上這種方式,而且 文件 也有可能不是通常所見(jiàn)到的那種。
寫(xiě)入文件 還可以是使用程序來(lái)生成一個(gè)文件,如
with codecs.open(filename, mode='w', encoding=encoding) as f:
f.write(u'pi: \u03c0')
以上Python代碼,這時(shí),就要在代碼中設(shè)置寫(xiě)入時(shí)的編碼方式。這個(gè)還只是寫(xiě)入到普通文件。如果是程序員,應(yīng)該還知道有一種文件叫做 標(biāo)準(zhǔn)輸出文件 而這種文件并不一定是傳統(tǒng)意義上的文件。而且,這里有一個(gè)比較容易誤解
標(biāo)準(zhǔn)輸出文件就是控制終端
其實(shí),標(biāo)準(zhǔn)輸出文件并不一定是控制終端,只不過(guò)常常和控制終端相連接,所以才有此誤解。
好,現(xiàn)在的最復(fù)雜的情況是在程序中寫(xiě)內(nèi)容到標(biāo)準(zhǔn)輸出文件需要指定編碼。
接下來(lái)的問(wèn)題是,既然內(nèi)容按照一定的編碼寫(xiě)到了標(biāo)準(zhǔn)輸出,這是一個(gè)寫(xiě)文件的過(guò)程,那么讀文件呢?
以下討論兩種情況。
- 標(biāo)準(zhǔn)輸出與終端連接:標(biāo)準(zhǔn)輸出往往與終端連接,將內(nèi)容顯示在終端上,這里其實(shí)已經(jīng)有了一個(gè)讀文件的過(guò)程。在傳統(tǒng)的讀文件過(guò)程中,有一個(gè)文本編輯器,有一個(gè)打開(kāi)文件的過(guò)程,但這里標(biāo)準(zhǔn)輸出文件并不是一個(gè)可以看的見(jiàn)的實(shí)體。而這個(gè)過(guò)程中,文本編輯器又在哪里呢?呵呵,這里 充當(dāng)文本編輯器角色的正是終端 。 所以通常所說(shuō)的設(shè)置終端的編碼就如同使用設(shè)置文本編輯器的編碼一樣。
- 標(biāo)準(zhǔn)輸出與管道連接:這里負(fù)責(zé) 讀文件 的是管道之后的程序。所以這里需要設(shè)置管道之后的程序中讀文件所使用的編碼。具體例子見(jiàn)PyMOTW中的codecs_stdin.py
其實(shí)要想搞清整個(gè)過(guò)程,有三個(gè)關(guān)鍵點(diǎn)最重要
- 寫(xiě)入過(guò)程指的是什么?
- 讀出過(guò)程指的是什么?
- 文件又指的是什么?
涉及文本操作的均離不開(kāi)以上三個(gè)部分,分析一個(gè)文本操作,找出以上三個(gè)部分的答案,讓寫(xiě)入過(guò)程和讀出過(guò)程的編碼一致,就能解決亂碼問(wèn)題了。