編碼-1

文章啓發來源:

  1. cnblogshtml

  2. 阮一峯python

  3. 知乎shell

字符編碼方式

note from wiki:ubuntu

從維基百科上獲得的一些理解,一個字符的unicode編碼是肯定的,可是在傳輸過程當中,因爲不一樣系統平臺的設計不一致,因此對unicode編碼的實現方式是有所不一樣的。unicode的實現方式成爲unicode轉換格式(簡稱UTF)例如對於一個包含基本7位ASCII字符的unicode文件,若是都使用2字節的原unicode編碼傳輸,會形成浪費。對於這種狀況可使用UTF-8編碼,它是一種變長編碼,對於基本ASCII字符仍然採用7位編碼表示,佔用一個字節。
意思其實就是,unicode規定了符號的二進制代碼的符號集,可是並無規定二進制代碼應該如何存儲。也就是說,在計算機的存儲中,一個字符的存放方式並不必定會與它的unicode編碼一致。這是由於採用了不一樣的編碼方式所致使的。segmentfault

本身整理的一些背景:

編碼一開始是使用ASCII碼來進行編碼的,可是這個編碼方式是針對英文爲基礎的國家的。後來,各個地區由於各自的須要,開始使用127位之後的擴展位。好比中國,由於幾萬個漢字,因此單靠單個127位是根本不夠的,因此就規定,使用高於127位的兩個字節來表示漢字。固然也就順便把原來的一些其餘擴展西方字符給出從新編碼了。即,全角字符(半角字符可類推)GB2312。
後來標準隨着發展,GBK變成了GB18030,即,只要第一個字節表示的十六進制數大於127,就表示漢字的開始。(DBCS,雙字節字符。臺灣地區的BIG5)。
後來unicode開始制定了,它的制定標準在上面的引用中能夠看到,使用的是兩個字節來表示字符。所以在unicode標準裏,不管是漢字的全角字符仍是英語的半角字符,都是一個字符,兩個字節。可是unicode如何在網絡上傳播也是一個問題。因而,便有了UTF。UTF與unicode的轉換關係以下:windows

note:網絡

0000 0000-0000 007F | 0xxxxxxx
    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

其中的x是要用左邊的十六進制碼轉化爲二進制碼後,代替相關的位。UTF-8的編碼規則很簡單,只有二條:編輯器

1)對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的unicode碼。所以對於英語字母,UTF-8編碼和ASCII碼是相同的。
    2)對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一概設爲10。剩下的沒有說起的二進制位,所有爲這個符號的unicode碼。

在查閱了幾篇blog後,舉個例子:好比說你如今的file用的是編輯器等(好比說是windows上的記事本,且設置它爲ASCIIunicode(實際上是帶BOM的utf-8))默認的編碼方式,那麼存儲的時候用的就是這種編碼方式對應的在硬盤中的存儲方式。好比說,此刻我用sublime 3打開,並且個人sublime 3 中只有utf系列和一些西文字體的編碼方式,那麼若是打開的文件用的是ASCII保存的文件,則此時會顯示的亂碼;而若是使用的是unicode的編碼方式,也是能打開的,並且不會出現亂碼的狀況。
在終端或者編輯器中,若是沒有進行特殊聲明的話,就會使用它們默認的編碼格式進行編碼,或者是GBK或者是UTF,若是是ascii的話,漢字字符是沒法存儲的,由於沒有配套的編碼。因此通常能顯示漢字的地方,使用的是GBK等等編碼格式,要轉碼的話,先轉換爲unicode,而後再轉換爲其餘東西。模塊化

關於python的encoding

參考知乎上的一個回答傳送門post

以我本身的理解就是:

  • 首先得分清楚編碼問題,在不一樣的環境中,編碼是不一樣的。在終端的狀況下,(windows 中是cmd,ubuntu 下的terminal,遠程登陸是xshell),因此他們的編碼是不一樣的。shell環境下,windows的編碼是GBK,ubuntu通常是utf-8。-------在文本編輯的狀況下,與上面的狀況相似,是根據編輯器的狀況決定的.

  • 在python中的狀況是,unicode(A,B)的意思是用B的編碼方案將A解碼,並將結果返回爲unicode字符串。因此通常在出現UnicodeDecodeError時候,錯誤的來源應該就是:

  1. 文件保存時的編碼方式是編輯器默認的保存方式,而在運行環境中默認的編碼方式與該文件方式並不相同,頗有多是有非ANIS的字符出現所致。由於環境沒法編碼該文件。

  2. 在文件保存的時候,帶有BOM 。BOM(byte order mark)是爲 UTF-16 和 UTF-32 準備的,用於標記字節序(byte order)。微軟在 UTF-8 中使用 BOM 是由於這樣能夠把 UTF-8 和 ASCII 等編碼明確區分開,但這樣的文件在 Windows 以外的操做系統裏會帶來問題。
    因此啊,最後在文件的頭裏面須要加入utf-8的說明,最好不要用BOM。

一點有意思的擴展,在pythonIDE中

兩種終端下的顯示

# 環境是sublime 3
    1 >>> u"知乎".encode('utf-8')
    2 '\xe7\x9f\xa5\xe4\xb9\x8e'
    3 >>> u"知乎".encode('gb2312')
    4 '\xd6\xaa\xba\xf5'
    5 >>> '知乎'.encode('utf-8')
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128)
   7 >>> '知乎'
     '\xe7\x9f\xa5\xe4\xb9\x8e'
   8 >>> u'知乎'
     u'\u77e5\u4e4e'
   9 >>> u'知乎'.encode('utf-8').decode('utf-8')
     u'\u77e5\u4e4e'    
   
# 環境是windows:
    >>>'知乎'
    '\xd6\xaa\xba\xf5'
    >>>u'知乎'
    u'\u77e5\u4e4e'
    >>> u"知乎".encode('utf-8')
    '\xe7\x9f\xa5\xe4\xb9\x8e'
    >>> u"知乎".encode('gb2312')
    '\xd6\xaa\xba\xf5'
    
    #仍是補充一下舉這個例子的本意:
    #從第七行(數字標出的,如下也是同樣)以及第一二行中能夠看出,兩個輸出結果是相同的,第一行說明  將    u'知乎'  unicode字符串按照utf-8的編碼方式進行編碼,並以字節串的形式輸出來。
    #可是若是換成的是 u'知乎' 的話,則表示的是將這個漢字用unicode編碼的形式存放。(猜想是自動調用了encode方法)。因此呢,第九行意思是將utf-8編碼的字符串用utf-8解碼出來。
    #下面又在windows上補充了下,能夠看出在不一樣的終端下,使用的編碼方式多是不一樣的,好比在windows上就有多是,當輸入漢字的時候,終端用gbk的編碼方式將漢字編碼。

最後再貼一個連接參考blog

總結

在這兩天的調試過程當中,開始將unicode的相關知識模塊化,因此在此也特意寫下這些東西,做爲一個總結。在寫代碼的時候,若是一個文件中有超過ascii的字符的話,那麼須要在py文件的第一行加以聲明。這是由於不一樣的環境,不一樣的編譯器所默認的編碼字符的格式是不一樣的。最好可以統一以unicode字符串爲基礎進行轉換。

update

這是一個在segmentfault網站上回答過的一個東西的連接。連接1

相關文章
相關標籤/搜索