python字符串編碼

python默認編碼前端

  python 2.x默認的字符編碼是ASCII,默認的文件編碼也是ASCIIpython

  python 3.x默認的字符編碼是unicode,默認的文件編碼是utf-8數據庫

 

中文亂碼問題編程

  不管以什麼編碼在內存裏顯示字符,存到硬盤上都是進制,因此編碼不對,程序就會出錯。windows

  常見編碼有ascii編碼(美國),GBK編碼(中國),shift_JIS編碼(日本),unicode(統一編碼)等。python3.x

  需要注意的是,存到硬盤上時是以何種編碼存的,再從硬盤上讀出來時,就必須以何種編碼讀,要否則就會出現亂碼問題數組

  常見的編碼錯誤的緣由有以下,出現亂碼時,按照編碼以前的關係,挨個排錯就能解決問題。編程語言

     python解釋器的默認編碼函數

     Terminal使用的編碼學習

     python源文件文件編碼

    操做系統的語言設置

  Python支持中文的編碼:utf-8gbkgb2312uft-8國際通用經常使用有數據庫、編寫代碼gbkwindowscmd使用

 

編碼轉換

  若是想要中國的軟件能夠正常的在美國人的電腦上實現,有下面兩種方法:

      讓美國人的電腦都裝上gbk編碼

      讓你的軟件編碼以utf-8編碼

   第一種方法不可現實,第二種方法比較簡單,可是也只能針對新開發的軟件,若是以前開發的軟件就是以gbk的編碼寫的,上百萬行代碼已經寫出去了,從新編碼成utf-8格式也會費很大力氣。

因此,針對已經用gbk開發的軟件項目如何進行編碼轉換,利用unicode的一個包含了跟全球全部國家編碼映射關係功能,就能夠實現編碼轉換。不管什麼編碼存儲的數據,只要咱們的軟件把數據從硬盤上讀到內存,轉成unicode來顯示便可,因爲全部的系統編程語言都默認支持unicode,全部咱們的gbk編碼軟件放在美國電腦上,加載到內存裏面,變成了unicode,中文就可正常展現

  相似用以下的轉碼的過程:

    源有編碼 -> unicode編碼 -> 目的編碼

    decode("UTF-8") 解碼 --> unicode  --> encode("gbk") 編碼

 

#_*_coding:utf-8_*_  的做用

  python2文件中,常常在文件開頭看到#_*_coding:utf-8 _*_ 」語句,它的做用是告訴python解釋器此.py文件是utf-8編碼,須要用utf-8編碼去讀取這個.py文件

 

python2.xbytes與python3.xbytes的區別

  Python2string處理爲原生的bytes類型,而不是 unicode。而Python3全部的 string均是unicode類型。

  在python2.x中,寫字符串,好比

 

>>>s = 」學習「
>>>print s
學習
>>>s    # 字節類型
'\xd1\xa7\xcf\xb0'

 

  雖說打印的是中文學習,可是直接調用變量s顯示的倒是一個個16進製表示的二進制字節,咱們稱這個爲byte類型,即字節類型,它把8個二進制組成一個byte,用16進製表示

  因此說python2.x的字符串其實更應該稱爲字符串,經過存儲的方式就能看出來,可是在python2.x中還有一個bytes類型,兩個是否相同呢,回答是確定的,在python2.x中,bytes==str

  python3.x把字符串變成了unicode,文件默認編碼utf-8這意味着,只要用python3.x,不管咱們的程序以那種語言開發,均可以在全球各國電腦上正常顯示。

  python3.x除了把字符串的編碼改爲了unicode,還把strbytes作了明確區分,str就是unicode格式的字符串,而bytes就是單純的二進制(補充一個問題,在python3.x中,只要unicode編碼,字符串就變成了bytes格式,不直接打印成gbk的字符,我以爲就是想經過這樣的方式明確的告訴你,想在python3.x中看字符,必須是unicode,其餘編碼一概是bytes格式)

 

深刻中文編碼問題

  python3內部使用的是unicode編碼,而外部卻要面對千奇百怪的各類編碼,好比做爲中國程序常常要面對的gbkgb2312utf8等,那這些編碼是怎麼轉換成內部的unicode呢?

  首先看一下源代碼文件中使用字符串的狀況。源代碼文件做爲文本文件就必然是以某種編碼形式存儲代碼的,python2默認源代碼文件是asci編碼,python3默認源代碼文件是utf-8編碼。好比python2代碼文件一個變量賦值:

    s1 = 'a'

    print s1

  python2認爲這個字符'a'就是一個asci編碼的字符,這個文件能夠正常執行,並打印出'a'字符。在僅僅使用英文字符的狀況下一切正常,可是若是用了中文,好比:

    s1 = '哈哈'

    print s1

  這個代碼文件被執行時就會出錯,就是編碼出了問題。python2默認將代碼文件內容看成asci編碼處理,但asci編碼中不存在中文,所以拋出異常。

  解決問題之道就是要讓python2解釋器知道文件中使用的是什麼編碼形式,對於中文,能夠用的常見編碼有utf-8gbkgb2312等。只需在代碼文件的最前端添加以下:

    # -*- coding: utf-8 -*-

  這就是告知python2解釋器,這個文件裏的文本是用utf-8編碼的這樣,python就會依照utf-8的編碼形式解讀其中的字符,而後轉換成unicode編碼內部處理使用。

  不過,若是你在Windows控制檯下運行此代碼的話,雖然程序是執行了,但屏幕上打印出的卻不是哈哈字。這是因爲python2編碼與控制檯編碼的不一致形成的。Windows下控制檯中的編碼使用的是gbk,而在代碼中使用的utf-8python2按照utf-8編碼打印到gbk編碼的控制檯下天然就會不一致而不能打印出正確的漢字。

  解決辦法一個是將源代碼的編碼也改爲gbk,也就是代碼第一行改爲:

    # -*- coding: gbk -*-

  另外一種方法是保持源碼文件的utf-8不變,而是在’哈哈’前面加個u字,也就是:

    s1=u’哈哈’

    print s1

  這樣就能夠正確打印出’哈哈’字了。這裏的這個u表示將後面跟的字符串以unicode格式存儲。python2會根據代碼第一行標稱的utf-8編碼識別代碼中的漢字’哈哈’,而後轉換成unicode對象。若是咱們用type查看一下’哈哈’的數據類型type(‘哈哈’),會獲得<type str>,而type(u’哈哈’),則會獲得<type unicode>

 

>>> type('哈哈')
<type 'str'>
>>> type(u'哈哈')
<type 'unicode'>

 

  也就是在字符前面加u就代表這是一個unicode對象,這個字會以unicode格式存在於內存中,而若是不加u,代表這僅僅是一個使用某種編碼的字符串,編碼格式取決於python2對源碼文件編碼的識別,這裏就是utf-8

  Python2在向控制檯輸出unicode對象的時候會自動根據輸出環境的編碼進行轉換,但若是輸出的不是unicode對象而是普通字符串,則會直接按照字符串的編碼輸出字符串,從而出現上面的現象。

  使用unicode對象的話,除了這樣使用u標記,還可使用unicode類以及字符串的encodedecode方法。

  unicode類的構造函數接受一個字符串參數和一個編碼參數,將字符串封裝爲一個unicode,好比在這裏,因爲咱們用的是utf-8編碼,因此unicode中的編碼參數使用'utf-8'將字符封裝爲unicode對象,而後正確輸出到控制檯:

    s1=unicode(‘’, ‘utf-8′)

    print s1

  另外,用decode函數也能夠將一個普通字符串轉換爲unicode對象。不少人都搞不明白python2字符串的decodeencode函數都是什麼意思。這裏簡要說明一下。

  decode函數是將普通字符串按照參數中的編碼格式進行解析,而後生成對應的unicode對象,好比在這裏咱們代碼用的是utf-8,那麼把一個字符串轉換爲unicode對象就是以下形式:

>>> s2 = '哈哈'.decode('utf-8')
>>> type(s2)
<type 'unicode'>

  這時,s2就是一個存儲了’哈哈’字符串unicode對象,其實就和unicode(‘哈哈’, utf-8)以及u’哈哈’是相同的。

  encode函數正好就是相反的功能,是將一個unicode對象轉換爲參數中編碼格式的普通字符,好比下面代碼:

>>> s3 = unicode('哈哈', 'utf-8').encode('utf-8')
>>> type(s3)
<type 'str'>
或者:
>>> s3 = '哈哈'.decode('utf-8').encode('utf-8')
>>> type(s3)
<type 'str'>

  s3如今又變回了utf-8的’哈’。一樣的,也可指定其它編碼格式,但要注意的是,用什麼格式編碼,就用什麼格式解碼,不然會出現中文亂碼問題。

  

字符編碼

  目前使用的編碼方式有:ASCII碼(一個字節)、Unicode碼(兩個字節)、UTF-8碼(可變長的編碼)咱們已經知道了,字符串也是一種數據類型,可是,字符串比較特殊的是還有一個編碼問題。

  由於計算機只能處理數字,若是要處理文本,就必須先把文本轉換爲數字才能處理。最先的計算機在設計時採用8個比特(bit)做爲一個字節(byte),因此,一個字節能表示的最大的整數就是255(二進制11111111=十進制255),若是要表示更大的整數,就必須用更多的字節。好比兩個字節能夠表示的最大整數是655354個字節能夠表示的最大整數是4294967295

  因爲計算機是美國人發明的,所以,最先只有127個字符被編碼到計算機裏,也就是大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII編碼,好比大寫字母A的編碼是65,小寫字母z的編碼是122可是要處理中文顯然一個字節是不夠的,至少須要兩個字節,並且還不能和ASCII編碼衝突,因此,中國製定了GB2312編碼,用來把中文編進去。能夠想獲得的是,全世界有上百種語言,日本把日文編到Shift_JIS裏,韓國把韓文編到Euc-kr裏,各國有各國的標準,就會不可避免地出現衝突,結果就是,在多語言混合的文本中,顯示出來會有亂碼。所以,Unicode應運而生。Unicode把全部語言都統一到一套編碼裏,這樣就不會再有亂碼問題了。Unicode標準也在不斷髮展,但最經常使用的是用兩個字節表示一個字符(若是要用到很是偏僻的字符,就須要4個字節)。現代操做系統和大多數編程語言都直接支持Unicode

  如今,捋一捋ASCII編碼和Unicode編碼的區別:ASCII編碼是1個字節,而Unicode編碼一般是2個字節。

  字母AASCII編碼是十進制的65,二進制的01000001

  字符'0'ASCII編碼是十進制的48,二進制的00110000,注意字符'0'和整數0是不一樣的;

  漢字中已經超出了ASCII編碼的範圍,用Unicode編碼是十進制的20013,二進制的01001110 00101101

  能夠猜想,若是把ASCII編碼的AUnicode編碼,只須要在前面補0就能夠,所以,AUnicode編碼是00000000 01000001

  新的問題又出現了:若是統一成Unicode編碼,亂碼問題今後消失了。可是,若是你寫的文本基本上所有是英文的話,用Unicode編碼比ASCII編碼須要多一倍的存儲空間,在存儲和傳輸上就十分不划算。

因此,本着節約的精神,又出現了把Unicode編碼轉化爲「可變長編碼」的UTF-8編碼。UTF-8編碼把一個Unicode字符根據不一樣的數字大小編碼成1-6個字節,經常使用的英文字母被編碼成1個字節,漢字一般是3個字節,只有很生僻的字符纔會被編碼成4-6個字節。若是你要傳輸的文本包含大量英文字符,用UTF-8編碼就能節省空間:

字符         ASCII                  Unicode                           UTF-8

 A         01000001        00000000 01000001               01000001

 中              x               01001110 00101101      11100100 10111000 10101101

UTF-8編碼有一個額外的好處,就是ASCII編碼實際上能夠被當作是UTF-8編碼的一部分,因此,大量只支持ASCII編碼的歷史遺留軟件能夠在UTF-8編碼下繼續工做。

 

編碼方式

1.ASCII

  如今咱們面臨了第一個問題:如何讓人類語言,好比英文被計算機理解?咱們以英文爲例,英文中有英文字母(大小寫)、標點符號、特殊符號。若是咱們將這些字母與符號給予固定的編號,而後將這些編號轉變爲二進制,那麼計算機明顯就可以正確讀取這些符號,同時經過這些編號,計算機也可以將二進制轉化爲編號對應的字符再顯示給人類去閱讀。由此產生了咱們最熟知的ASCII碼。ASCII 碼使用指定的7 位或8 位二進制數組合來表示128 256 種可能的字符。這樣在大部分狀況下,英文與二進制的轉換就變得容易多了。

 

2.GB2312

  雖然計算機是美國人發明的,可是全世界的人都在使用計算機。如今出現了另外一個問題:如何讓中文被計算機理解?這下麻煩了,中文不像拉丁語系是由固定的字母排列組成的。ASCII 碼顯然沒辦法解決這個問題,爲了解決這個問題中國國家標準總局1980年發佈《信息交換用漢字編碼字符集》提出了GB2312編碼,用於解決漢字處理的問題。1995年又頒佈了《漢字編碼擴展規範》(GBK)。GBKGB 23121980國家標準所對應的內碼標準兼容,同時在字彙一級支持ISO/IEC106461GB 130001的所有中、日、韓(CJK)漢字,共計20902字。這樣咱們就解決了計算機處理漢字的問題了。

 

3.Unicode

  如今英文和中文問題被解決了,但新的問題又出現了。全球有那麼多的國家不只有英文、中文還有阿拉伯語、西班牙語、日語、韓語等等。難不成每種語言都作一種編碼?基於這種狀況一種新的編碼誕生了:UnicodeUnicode又被稱爲統一碼、萬國碼;它爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼,以知足跨語言、跨平臺進行文本轉換、處理的要求。Unicode支持歐洲、非洲、中東、亞洲(包括統一標準的東亞象形漢字和韓國表音文字)。這樣無論你使用的是英文或者中文,日語或者韓語,在Unicode編碼中都有收錄,且對應惟一的二進制編碼。這樣你們都開心了,只要你們都用Unicode編碼,那就不存在這些轉碼的問題了,什麼樣的字符都可以解析了。

 

4.UTF-8

  可是,因爲Unicode收錄了更多的字符,可想而知它的解析效率相比ASCII碼和GB2312的速度要大大下降,並且因爲Unicode經過增長一個高字節對ISO Latin-1字符集進行擴展,當這些高字節位爲0時,低字節就是ISO Latin-1字符。對能夠用ASCII表示的字符使用Unicode並不高效,由於UnicodeASCII佔用大一倍的空間,而對ASCII來講高字節的0毫無用處。爲了解決這個問題,就出現了一些中間格式的字符集,他們被稱爲通用轉換格式,即UTFUnicode Transformation Format)。而咱們最經常使用的UTF-8就是這些轉換格式中的一種。在這裏咱們不去研究UTF-8究竟是如何提升效率的,你只須要知道他們之間的關係便可。

相關文章
相關標籤/搜索