自己經(jīng)常在Linux和Windows下使用各種各樣的軟件棍辕,經(jīng)常遇到的亂碼的問題锯岖。
之前的對策是google XX軟件 亂碼 得到的結(jié)果往往是這樣子的
Step1... Step2... Step3... ....
于是自己也跟著做,有時能成功,但有時依然亂碼,只好放棄使用這個軟件脖母。
我想我的問題一直不知道為什么會出現(xiàn)亂碼,當(dāng)然闲孤,并不是完全不知谆级,說起編碼,也能說出個一二三來崭放,什么unicode, utf-8, 轉(zhuǎn)換編碼之類的哨苛。但自己并沒有一個清晰的概念。所以一直出問題币砂,也不知道問題的根源在哪里建峭。所以出了問題,解決問題的方式只能上網(wǎng)搜索决摧,純屬碰運氣亿蒸。
直到前一段時間讀到The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets這篇文章,發(fā)現(xiàn)自己有了那么一點點清晰的概念掌桩,之后在學(xué)Python Module of the Week中的編碼時边锁,仔細思考了一下,總算把亂碼產(chǎn)生的原因想的大概明白了波岛。
其實茅坛,說起來很簡單,對于文本來說则拷,主要有兩種操作
- 將文本寫入文件
- 從文件中讀取
其中如果寫入文件時和讀取文件時使用的編碼不一樣贡蓖,則可能會產(chǎn)生亂碼,到這里似乎還很簡單煌茬。
一般情形是這樣子的斥铺,使用一個文件編輯器編輯一個文件,然后保存坛善,保存的時候選取某一種編碼晾蜘,這一過程對應(yīng) 1. 寫入文件時的編碼。
讀取文件時眠屎,往往使用文本編輯器打開一個文件剔交,如果此時文本編輯器設(shè)定的編碼方式與文件保存時使用的編碼方式一樣,那么顯示的時候就不會有亂碼改衩,如果不一樣岖常,則可能產(chǎn)生亂碼(如果保存時使用的編碼是顯示時設(shè)置的編碼的子集,一般會正常顯示)燎字。這一過程對應(yīng) 2. 從文件中讀取 腥椒。
由以上可以看的出來,使用文本編輯器保存時是寫入候衍,使用文本編輯器打開文件時是讀取笼蛛。這種情況很簡單。
但是蛉鹿, 寫入文件 和 讀取文件 并非只有以上這種方式滨砍,而且 文件 也有可能不是通常所見到的那種。
寫入文件 還可以是使用程序來生成一個文件妖异,如
with codecs.open(filename, mode='w', encoding=encoding) as f:
f.write(u'pi: \u03c0')
以上Python代碼惋戏,這時,就要在代碼中設(shè)置寫入時的編碼方式他膳。這個還只是寫入到普通文件响逢。如果是程序員,應(yīng)該還知道有一種文件叫做 標(biāo)準(zhǔn)輸出文件 而這種文件并不一定是傳統(tǒng)意義上的文件棕孙。而且舔亭,這里有一個比較容易誤解
標(biāo)準(zhǔn)輸出文件就是控制終端
其實,標(biāo)準(zhǔn)輸出文件并不一定是控制終端蟀俊,只不過常常和控制終端相連接钦铺,所以才有此誤解。
好肢预,現(xiàn)在的最復(fù)雜的情況是在程序中寫內(nèi)容到標(biāo)準(zhǔn)輸出文件需要指定編碼矛洞。
接下來的問題是,既然內(nèi)容按照一定的編碼寫到了標(biāo)準(zhǔn)輸出烫映,這是一個寫文件的過程沼本,那么讀文件呢?
以下討論兩種情況窑邦。
- 標(biāo)準(zhǔn)輸出與終端連接:標(biāo)準(zhǔn)輸出往往與終端連接擅威,將內(nèi)容顯示在終端上,這里其實已經(jīng)有了一個讀文件的過程冈钦。在傳統(tǒng)的讀文件過程中郊丛,有一個文本編輯器,有一個打開文件的過程瞧筛,但這里標(biāo)準(zhǔn)輸出文件并不是一個可以看的見的實體厉熟。而這個過程中,文本編輯器又在哪里呢较幌?呵呵揍瑟,這里 充當(dāng)文本編輯器角色的正是終端 。 所以通常所說的設(shè)置終端的編碼就如同使用設(shè)置文本編輯器的編碼一樣乍炉。
- 標(biāo)準(zhǔn)輸出與管道連接:這里負責(zé) 讀文件 的是管道之后的程序绢片。所以這里需要設(shè)置管道之后的程序中讀文件所使用的編碼滤馍。具體例子見PyMOTW中的codecs_stdin.py
其實要想搞清整個過程,有三個關(guān)鍵點最重要
- 寫入過程指的是什么底循?
- 讀出過程指的是什么巢株?
- 文件又指的是什么?
涉及文本操作的均離不開以上三個部分熙涤,分析一個文本操作阁苞,找出以上三個部分的答案,讓寫入過程和讀出過程的編碼一致祠挫,就能解決亂碼問題了那槽。