編碼問題詳解

編碼問題詳解

1、總述

編碼python

大小linux

支持語言編程

ASCII小程序

1個字節(byte)=8bit=2位16進制數,表示127個字符windows

英文瀏覽器

Unicode服務器

用至多2個字節表示65535個字符。(16bit=2byte)之間的數字來表示全部字符 (python3在內存中的編碼方式)網絡

全部語言編程語言

Unicode2函數

用至多4個字節表示全部字符

 

UTF-8

1-6個字節,英文字母1個字節,漢字3個字節,生僻字4-6個字節(外存或網絡通訊中的編碼方式)

全部語言

 

 

2、ASCII

標準ASCII 碼,使用7 位二進制數(第1位二進制爲0)來表示全部的大寫和小寫字母,數字0 到九、標點符號,以及在美式英語中使用的特殊控制字符

最先只有127個字母被編碼到計算機裏,也就是大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII編碼,好比大寫字母A的編碼是65,小寫字母z的編碼是122。

3、Unicode

1. 什麼是unicode

 

要處理中文顯然一個字節是不夠的,至少須要兩個字節,並且還不能和ASCII編碼衝突,因此,中國製定了GB2312編碼,用來把中文編進去。

全世界有上百種語言,Unicode把全部語言都統一到一套編碼裏,這樣就不會再有亂碼問題了。

Unicode標準也在不斷髮展,但最經常使用的是用1-2個字節表示一個字符(若是要用到很是偏僻的字符,就須要4個字節)。現代操做系統和大多數編程語言都直接支持Unicode。

 

2. 容易歧義的2字節問題

  unicode的第一個版本是用兩個字節(16bit)來表示全部字符實際上這麼說容易讓人產生歧義,咱們總以爲兩個字節就表明保存在計算機中時是兩個字節因而任何字符若是用unicode表示的話保存下來都佔兩個字節.其實這種說法是錯誤的.

  其實Unicode涉及到兩個步驟,首先是定義一個規範,給全部的字符指定一個惟一對應的數字,這徹底是表示問題,能夠跟計算機沒半毛錢關係.第二步纔是怎麼把字符對應的數字保存在計算機中,這才涉及到實際在計算機中佔多少字節空間

Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。

  因此咱們也能夠這樣理解,Unicode是用0至65535之間的數字來表示全部字符.其中0至127這128個數字表示的字符仍然跟ASCII徹底同樣.unicode兼容了ascii,即若是是英文的,前8位就是0,後8位就是ascii;若是前8位有值,就是中文編碼。例如,65536是2的16次方.這是第一步.第二步就是怎麼把0至65535這些數字轉化成01串保存到計算機中這確定就有不一樣的保存方式了因而出現了UTF(unicode transformation format),有UTF-8,UTF-16等存儲方式。

3. 總結

 

綜上,python字符串,在運行時,在內存中保存爲Unicode數據,2個字節做爲一個字,但保存.py文件到磁盤、網絡中,會編碼爲utf-8等格式,它們以字節碼(字節串bytes)的形式保存在介質上。而想從網絡或磁盤中讀取數據,就是要把utf-8或其餘編碼從字節碼(字節串bytes)解碼爲unicode字符串。

 

 

python3中的字符串與python2中的u'字符串',都是unicode,只能encode,因此不管如何打印都不會亂碼,由於能夠理解爲從內存打印到內存,即內存->內存,unicode->unicode

另外,文件(如txt)的保存又是另外一種狀況,windows平臺下使用python內置函數 open() 時發現,當不傳遞encoding參數時,會自動採用gbk(cp936)解碼打開文件linux默認會採用utf-8解碼,而當下很大部分軟件的編碼方式都是UTF-8,因此打開會報錯。

微軟發佈系統因爲沒有使用unicode編碼,因此windows要發佈中文版,日本版,德國版...而蘋果用的是unicode,只須要一套系統,直接改編碼便可。

4、數據傳輸與編碼

在計算機內存中,統一使用Unicode編碼,當須要保存到硬盤或者須要傳輸的時候,轉換爲UTF-8編碼。

Linux系統,用記事本編輯的時候,從文件讀取的UTF-8字符被解碼Unicode字符到內存裏,編輯完成後,保存的時候再把Unicode編碼UTF-8保存到文件:

 

 

瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換爲UTF-8再傳輸到瀏覽器:

 

 

5、UTF-8

UTF-8是Unicode的實現方式之一。UTF-8 是一種 Unicode 的編碼方式,主要做用對 Unicode 碼的數據進行轉換,轉換後方便存儲和網絡傳輸。本着節約的精神,又出現了把Unicode編碼轉化「可變長編碼」的UTF-8編碼(unicode transformation format)UTF-8編碼把一個Unicode字符根據不一樣的數字大小編碼成1-6個字節,經常使用的英文字母被編碼成1個字節,漢字一般是3個字節,只有很生僻的字符纔會被編碼成4-6個字節。若是你要傳輸的文本包含大量英文字符,用UTF-8編碼就能節省空間。

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

8不是指一個字節,難道一個字節表示一個字符?實際上不是.當用UTF-8時表示一個字符是可變的,有多是用一個字節表示一個字符,也多是兩個,三個..反正是根據字符對應的數字大小來肯定

 

UTF-8表示"漢"

Unicode符號範圍        | UTF-8編碼方式
(十六進制)       | (二進制)
--------------------+---------------------------------------------
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

UTF-8就有複雜點.由於此時程序是把一個字節一個字節的來讀取,而後再根據字節中開頭的bit標誌來識別是該把1個仍是兩個或三個字節作爲一個單元來處理.

0xxxxxxx,若是是這樣的01串,也就是以0開頭後面是啥就不用管了XX表明任意bit.就表示把一個字節作爲一個單元.就跟ASCII徹底同樣.

110xxxxx 10xxxxxx.若是是這樣的格式,則把兩個字節當一個單元

1110xxxx 10xxxxxx 10xxxxxx 若是是這種格式則是三個字節當一個單元.(漢子一般在這個區域)

這是約定的規則.你用UTF-8來表示時必須遵照這樣的規則咱們知道UTF-16不須要用啥字符來作標誌,因此兩字節也就是2的16次能表示65536個字符.

UTF-8因爲裏面有額外的標誌信息,全部一個字節只能表示2的7次方128個字符,兩個字節只能表示2的11次方2048個字符.而三個字節能表示2的16次方,65536個字符

因爲"漢"的編碼6C4927721大於2048了全部兩個字節還不夠,只能用三個字節來表示要用1110xxxx 10xxxxxx 10xxxxxx這種格式.把27721對應的二進制從左到右填充XXX符號.

由上面咱們能夠看出UTF-8在局部的字節錯誤(丟失、增長、改變)不會致使連鎖性的錯誤,由於 UTF-8 的字符邊界很容易檢測出來,因此容錯性較高。

6、UTF-16

UTF-16比較好理解,就是任何字符對應的數字都用兩個字節來保存咱們一般對Unicode的誤解就是把Unicode與UTF-16等同了可是很顯然若是都是英文字母這作有點浪費.明明用一個字節能表示一個字符爲啥整兩個啊

因而UTF-8和UTF-16的優劣很容易就看出來了若是所有英文或英文與其餘文字混合,但英文佔絕大部分,用UTF-8就比UTF-16節省了不少空間.而若是所有是中文這樣相似的字符或者混合字符中中文佔絕大多數.UTF-16就佔優點了

你可能會問當用程序打開一個文件時咱們怎麼知道那是用的UTF-8仍是UTF-16啊.天然會有點啥標誌,在文件的開頭幾個字節就是標誌

EF BB BF 表示UTF-8

FE FF 表示UTF-16.

 

例如,中文字"漢"對應的unicode是6C4927721

UTF-16表示的話就是01101100   01001001(共16 bit,兩個字節)

 

 

 

7、UnicodeUTF-8之間的轉換

 

"嚴"的Unicode碼是4E25,UTF-8編碼是E4B8A5,二者是不同的。它們之間的轉換能夠經過程序實現。

Windows平臺下,有一個最簡單的轉化方法,就是使用內置的記事本小程序Notepad.exe。打開文件後,點擊"文件"菜單中的"另存爲"命令,會跳出一個對話框,在最底部有一個"編碼"的下拉條。

 

裏面有四個選項:ANSI,Unicode,Unicode big endian 和 UTF-8。

1)ANSI是默認的編碼方式。對於英文文件是ASCII編碼,對於簡體中文文件是GB2312編碼(只針對Windows簡體中文版,若是是繁體中文版會採用Big5碼)。

2)Unicode編碼指的是UCS-2編碼方式,即直接用兩個字節存入字符的Unicode碼。這個選項用的little endian格式。

3)Unicode big endian編碼與上一個選項相對應。

4)UTF-8編碼,也就是上一節談到的編碼方法。

選擇完"編碼方式"後,點擊"保存"按鈕,文件的編碼方式就馬上轉換好了。

 

 

8、Unicode2

前面說的都是unicode的第一個版本.但65536顯然不算太多的數字,用它來表示經常使用的字符是沒一點問題.足夠了,但若是加上不少特殊的就也不夠了.因而從1996年開始又來了第二個版本.用四個字節表示全部字符.這樣就出現了UTF-8,UTF16,UTF-32.原理和以前確定是徹底同樣的,UTF-32就是把全部的字符都用32bit也就是4個字節來表示.而後UTF-8,UTF-16就視狀況而定了UTF-8能夠選擇1至8個字節中的任一個來表示.而UTF-16只能是選兩字節或四字節.

前面說了要知道具體是哪一種編碼方式,須要判斷文本開頭的標誌

9、Big-Endian and Little-Endian

 

填充方式能夠不同,因而就出現了Big-Endian,Little-Endian的術語.Big-Endian就是從左到右,Little-Endian是從右到左

EF BB BF    UTF-8
FE FF     UTF-16/UCS-2, little endian
FF FE     UTF-16/UCS-2, big endian
FF FE 00 00  UTF-32/UCS-4, little endian.
00 00 FE FF  UTF-32/UCS-4, big-endian.

Unicode碼能夠採用UCS-2格式直接存儲。以漢字"嚴"爲例,Unicode碼是4E25,須要用兩個字節存儲,一個字節是4E,另外一個字節是25。存儲的時候,4E在前,25在後,就是Big endian方式;25在前,4E在後,就是Little endian方式。

那麼很天然的,就會出現一個問題:計算機怎麼知道某一個文件到底採用哪種方式編碼?

Unicode規範中定義,每個文件的最前面分別加入一個表示編碼順序的字符,這個字符的名字叫作"零寬度非換行空格"(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。這正好是兩個字節,並且FF比FE大1。若是一個文本文件的頭兩個字節是FE FF,就表示該文件採用大頭方式;若是頭兩個字節是FF FE,就表示該文件採用小頭方式。

 

下面,舉一個實例。

打開"記事本"程序Notepad.exe,新建一個文本文件,內容就是一個"嚴"字,依次採用ANSI,Unicode,Unicode big endian 和 UTF-8編碼方式保存。

而後,用文本編輯軟件UltraEdit中"十六進制功能",觀察該文件的內部編碼方式。

1)ANSI:文件的編碼就是兩個字節"D1 CF",這正是"嚴"的GB2312編碼,這也暗示GB2312是採用大頭方式存儲的。

2)Unicode:編碼是四個字節"FF FE 25 4E",其中"FF FE"代表是小頭方式存儲,真正的編碼是4E25。

3)Unicode big endian:編碼是四個字節"FE FF 4E 25",其中"FE FF"代表是大頭方式存儲。

4)UTF-8:編碼是六個字節"EF BB BF E4 B8 A5",前三個字節"EF BB BF"表示這是UTF-8編碼,後三個"E4B8A5"就是"嚴"的具體編碼,它的存儲順序與編碼順序是一致的

 

10、一些抉擇

 

UTF-16 並非一個完美的選擇,它存在幾個方面的問題:

  1. UTF-16 能表示的字符數有 6 萬多,看起來不少,可是實際上目前 Unicode 5.0 收錄的字符已經達到 99024 個字符,早已超過 UTF-16 的存儲範圍;這直接致使 UTF-16 地位頗爲尷尬——若是誰還在想着只要使用 UTF-16 就能夠高枕無憂的話,恐怕要失望了
  2. UTF-16 存在大小端字節序問題,這個問題在進行信息交換時特別突出——若是字節序未協商好,將致使亂碼;若是協商好,可是雙方一個採用大端一個採用小端,則必然有一方要進行大小端轉換,性能損失不可避免(大小端問題其實不像看起來那麼簡單,有時會涉及硬件、操做系統、上層軟件多個層次,可能會進行屢次轉換)
  3. 另外,容錯性低有時候也是一大問題——局部的字節錯誤,特別是丟失或增長可能致使全部後續字符所有錯亂,錯亂後要想恢復,可能很簡單,也可能會很是困難。(這一點在平常生活裏你們感受彷佛可有可無,可是在不少特殊環境下倒是巨大的缺陷)

目前支撐咱們繼續使用 UTF-16 的理由主要是考慮到它是雙字節的,在計算字符串長度、執行索引操做時速度很快。固然這些優勢 UTF-32 都具備,但不少人畢竟仍是以爲 UTF-32 太佔空間了。

反過來 UTF-8 也不完美,也存在一些問題:

  1. 文化上的不平衡——對於歐美地區一些以英語爲母語的國家 UTF-8 簡直是太棒了,由於它和 ASCII 同樣,一個字符只佔一個字節,沒有任何額外的存儲負擔;可是對於中日韓等國家來講,UTF-8 實在是太冗餘,一個字符居然要佔用 3 個字節,存儲和傳輸的效率不但沒有提高,反而降低了。因此歐美人民經常絕不猶豫的採用 UTF-8,而咱們卻總是要猶豫一下子
  2. 變長字節表示帶來的效率問題——你們對 UTF-8 疑慮重重的一個問題就是在於其由於是變長字節表示,所以不管是計算字符數,仍是執行索引操做效率都不高。爲了解決這個問題,經常會考慮把 UTF-8 先轉換爲 UTF-16 或者 UTF-32 後再操做,操做完畢後再轉換回去。而這顯然是一種性能負擔。



然,UTF-8 的優勢也不能忘了:

  1. 字符空間足夠大,將來 Unicode 新標準收錄更多字符,UTF-8 也能妥妥的兼容,所以不會再出現 UTF-16 那樣的尷尬
  2. 不存在大小端字節序問題,信息交換時很是便捷
  3. 容錯性高,局部的字節錯誤(丟失、增長、改變)不會致使連鎖性的錯誤,由於 UTF-8 的字符邊界很容易檢測出來,這是一個巨大的優勢(正是爲了實現這一點,我們中日韓人民不得不忍受 3 字節 1 個字符的苦日子)


那麼到底該如何選擇呢?
由於不管是 UTF-8 和 UTF-16/32 都各有優缺點,所以選擇的時候應當立足於實際的應用場景。例如在個人習慣中,存儲在磁盤上或進行網絡交換時都會採用 UTF-8,而在程序內部進行處理時則轉換爲 UTF-16/32。對於大多數簡單的程序來講,這樣作既能夠保證信息交換時容易實現相互兼容,同時在內部處理時會比較簡單,性能也還算不錯。(基本上只要你的程序不是 I/O 密集型的均可以這麼幹,固然這只是我粗淺的認識範圍內的經驗,極可能會被無情的反駁)

11、漢字編碼

 1個漢字是多少個字節?

: GBK(2個字節--windows)/ UTF-8(3個字節--linux)

GBK是ASCII的擴展集,ASCII使用一個字節,即8個二進制位,來表徵英文字母和一些符號,一個字節能夠最多表示2的8次方即256個字符。前127個被稱爲ASCII字符集,後續在ASCII的基礎上進行擴展,將剩餘的127個用來表徵漢字,但漢字太多,因此不得不在必要時使用2個字符來表示更多的漢字,被稱爲GB2312字符集,後來仍然不夠,又進一步擴展成GBK字符集。因此在此字符集中,英文佔一個字節,漢字則佔兩個字節。

經常使用編碼:中國大陸只有2種

 國標系列: GB18030(GBK(GB2312))(windows經常使用)

 例如,windows裏建一個txt文件,文件裏寫10個漢字,文件是20字節,由於是gbk格式保存的。

  國際標準: UNICODE (2或4字節,全部國家編碼不會衝突)<---> UTF-8 (Linux / Mac OS X / IOS / Android等經常使用)

 例如,在linux裏建一個txt文件,文件裏寫10個漢字,文件是30字節,由於是utf-8

12、Python的編碼相關問題

1. ord()chr()

功能:

ord(str)   返回一個字符的unicode編碼

chr(unicode)  返回unicode對應的字符

 

>>> ord("發揮好")

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: ord() expected a character, but string of length 3 found

出錯緣由:一次只能查詢一個字符的unicode編碼

 

>>> ord("f")

102

 

>>> chr(102)

'f'

 

>>> ord("折")

25240

 

>>> chr(25240)

'折'

 

>>> ord('中')

20013

 

>>> ord('\u4e2d')   --python3.0支持嵌入unicode,這是「中」的unicode

20013

 

2. 字符串中使用的幾種前綴

\u 後面通常跟4位16進制,表示2字節的unicode

\x 後跟2位16進制數,能夠表示1字節的unicode(包括ASCII的所有內 容,也包括非ASCII的一些1字節的unicode)

b   表示原始字節值。前面加b表明使用ASCII字符集建立bytes字節串,只能建立ASCII字符集中存在的字符,中文字符前加b會報錯(由於最大隻能存一字節數據8位二進制數裏面\x後跟2位16進制數,表示1字節,只能存ascii碼。若是能顯示這個字符,則顯示這個字符。

Str: 能處理Unicode

 

>>> '\xEE'

'î'

 

>>> '\x41'

'A'

 

>>> '\xffff'

'ÿff'    --只把前2位當作16進制的unicode編碼,其餘按unicode表示的字符原樣輸出。

 

>>> '\x01c'

'\x01c'    --01的ascii和unicode碼不是字符,則按普通字節原樣輸出

 

>>> '\u4f60'

'你'

 

>>> '\u4f609090'  

--只把前4位當作16進制的unicode編碼,其餘按unicode表示的字符原樣輸出。

 

'你9090'

 

>>> '\U00000041'

'A'

 

 

>>> b'abc'

b'abc'

 

>>> b'\xff22'

b'\xff22' --字節串 \xff若不是ascii碼,會原樣輸出。

 

>>> b'\x30'

b'0'      --字節串 能顯示爲ASCII碼會顯示對應的字符

 

>>> b'5'

b'5'

 

>>> b'我'

  File "<stdin>", line 1

SyntaxError: bytes can only contain ASCII literal characters.

-- 只能存一個個字節,不能超過1字節

 

3. 編碼與解碼

Python程序在運行過程當中,字符串在內存中,只容許以unicode16/32編碼存儲。

 

外部文件(硬盤中)中能夠有gbk,gb1312,gb18030,ascii,utf-8(字節串),但一旦造成python字符串,在python程序裏運行時,必定是unicode全世界統一編碼,即從外部編碼獲取最終的unicode值。

 

從內部字符串(內存)轉到gbk,gb1312,gb18030,ascii,utf-8外部編碼(即存到外存裏),必須先編碼S.encode(‘gbk’)。encode()函數能夠將字符串轉換爲對應字符集的bytes(字節串)

 

>>> str='abc'

>>> str.decode()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

AttributeError: 'str' object has no attribute 'decode'

 

以上出錯的緣由:

Python字符串在內存中是unicode,不須要再解碼成unicode了。

 

Print(str) 函數: 根據unicode打印字符串。若是str不是unicode,而是utf-8要解碼爲unicode才能打印出想要的樣子,直接打印會打印成字節串bytes。

 

從外部編碼(硬盤)轉到內部字符串(python解釋器、內存)用解碼B.decode(‘gbk’)

 

 

 

例如:str ---> bytes 字符串編碼成爲字節串

 b = s.encode(encoding='utf-8')

 

bytes---> str 字節串解碼成爲字符串

 s = b.decode(encoding='utf-8')

 

 

>>> u = '中文'                 # 指定字符串類型對象u

 

>>> str1 = u.encode('gb2312')  

# 以gb2312編碼對u進行編碼,得到bytes字節串類型對象

 

>>> print(str1) 

b'\xd6\xd0\xce\xc4'  #打印字節碼

 

>>> str2 = u.encode('gbk')     

# 以gbk編碼對u進行編碼,得到bytes字節串類型對象

 

>>> print(str2)

b'\xd6\xd0\xce\xc4'

 

>>> str3 = u.encode('utf-8')   

# 以utf-8編碼對u進行編碼,得到bytes字節串類型對象

 

>>> print(str3)

b'\xe4\xb8\xad\xe6\x96\x87'

 

>>> u1 = str1.decode('gb2312') # 以gb2312編碼對字節串str1進行解碼,得到unicode類型對象

 

>>> print('u1')

'中文'

 

>>> u2 = str1.decode('utf-8')  # 報錯,由於str1是gb2312編碼的

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte

 

>>> 'x'+b'y'.decode()

'xy'

 

>>> 'x'.encode()+b'y'

b'xy'

 

4. python編碼註釋

編碼註釋的功能:告訴python解釋器,這個腳本用什麼編碼來解碼

 

在源文件的第一行或第二行寫入以下內容:

  # -*- coding:gbk -*-

  # 設置源文件編碼格式爲:gbk

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

  # 設置源文件編碼格式爲:UTF-8

 

世界上存在着多種編碼方式,同一個二進制數字能夠被解釋成不一樣的符號。所以,要想打開一個文本文件,就必須知道它的編碼方式,不然用錯誤的編碼方式解碼,就會出現亂碼。

注意:不寫編碼註釋的話。在windows下寫的代碼(gbk編碼)在linux下不能執行,由於linux會把這些gbk當作utf-8(Linux默認把中文當作utf-8),嘗試按utf-8的格式把這些代碼解碼爲unicode,在此過程當中會出錯。若是寫了編碼註釋linux會gbk的格式將其解碼爲unicode字符串,在python環境運行打印

 

實驗:

 

Windows下編輯python文本文件,文件保存爲gbk格式。

 

 

C:\code\studybook_3>python zs.py

  File "zs.py", line 1

SyntaxError: Non-UTF-8 code starting with '\xb9' in file zs.py on line 1, b

 encoding declared; see http://python.org/dev/peps/pep-0263/ for details

報錯緣由:python解釋器默認使用utf-8解碼文件,而文件是用gbk編碼的。

下面加上編碼註釋:

 

 

 

執行成功,編碼註釋告訴python解釋器,要用gbk把文件解碼爲unicode字符串,再內存中打印。在Linux中也能正常打印。

 

 

 

 

Windows下編輯python文本文件,文件保存爲utf-8格式。

 

 

運行正常,python解釋器默認使用utf-8解碼文件,而文件是用utf-8編碼的,故能夠正常解碼爲unicode。Linux同理。

 

 

5. Python文件編碼

Windows下,系統默認用gbk\utf-8解碼文件。

Linux下,系統默認用utf-8解碼文件。

1 生成gbk文件

s='小甲'

with open("gbk2222.txt","w",encoding = "gbk") as f:

f.write(s)

Win下,以上代碼生成gbk編碼格式文件gbk2222.txt,用記事本自動用gbk解碼,能打開;Linux下,系統默認用utf-8解碼則不能打開。

 

 

 

 

2 生成utf-8文件

s='小甲'

with open("utf2222.txt","w",encoding = "utf-8") as f:

f.write(s)

Win下,以上代碼生成utf-8編碼格式文件utf2222.txt,用記事本自動用utf-8解碼,能打開;Linux下,系統默認用utf-8解碼也能打開。

 

 

 

 

 

 

3

with open("what","w") as f:

f.write(s)

Win下,不指定編碼格式,生成文件what。

用記事本打開,發現文件默認保存爲本地編碼,即window保存爲gbk編碼;linux保存爲utf-8編碼。

4查看默認編碼

windows下執行如下操做:

>>> import sys,locale

>>> sys.getdefaultencoding()

'utf-8'

>>> locale.getdefaultlocale()

('zh_CN', 'cp936')

以上說明,python內存默認採用utf-8 對.py文件進行解碼。

Window默認採用cp926對文本文件進行解碼。

 

linux下執行如下操做:

>>> import sys,locale

>>> sys.getdefaultencoding()

'utf-8'

>>> locale.getdefaultlocale()

('zh_CN', 'UTF-8')

以上說明,python內存默認採用utf-8 對.py文件進行解碼。

linux默認採用UTF-8對文本文件進行解碼。

 

5 查看不一樣系統文本文件的默認編碼

1)Windows記事本下建文本文件,輸入漢字「中」 ,

默認保存爲ANSI 編碼文本,即GBK,2字節。

windows記事本中顯示正確,在linux打開亂碼。由於linux是按utf-8解碼打開文本文件的。

不一樣的國家和地區制定了不一樣的標準,由此產生了 GB23十二、GBK、GB18030、Big五、Shift_JIS 等各自的編碼標準。這些使用多個字節來表明一個字符的各類漢字延伸編碼方式,稱爲 ANSI 編碼。在簡體中文Windows操做系統中,ANSI 編碼表明 GBK 編碼;在繁體中文Windows操做系統中,ANSI編碼表明Big5;在日文Windows操做系統中,ANSI 編碼表明 Shift_JIS 編碼。

2)Windows記事本下建文本文件,輸入漢字「中」,

默認保存爲utf-8編碼文本,6字節。

windows記事本中顯示正確,在linux打開,系統會按unicode解碼後正常顯示。

 

3)linux下建文本文件,輸入漢字「中」,

默認保存爲utf-8編碼文本,4字節。

Windows記事本顯示正常,win會按utf-8解碼後讀取unicode.

 

6 文件指定編碼寫入測試

Windows記事本寫以下文件,用utf-8保存

 

 

運行後:

 

 

Python解釋器內部,使用utf-8解碼文件爲unicode,而後打印。

文件utf1寫入磁盤是utf-8編碼 在win能打開,在linux能打開;

文件gbk1寫入磁盤是gbk編碼 在win能打開,在linux不能打開(linux只能用utf-8解碼);

文件jis1寫入磁盤是jis編碼 在win不能打開,在linux不能打開;

 

附:ASCII碼錶具體以下所示

Bin

(二進制)

Oct

(八進制)

Dec

(十進制)

Hex

(十六進制)

縮寫/字符

解釋

0000 0000

00

0

0x00

NUL(null)

空字符

0000 0001

01

1

0x01

SOH(start of headline)

標題開始

0000 0010

02

2

0x02

STX (start of text)

正文開始

0000 0011

03

3

0x03

ETX (end of text)

正文結束

0000 0100

04

4

0x04

EOT (end of transmission)

傳輸結束

0000 0101

05

5

0x05

ENQ (enquiry)

請求

0000 0110

06

6

0x06

ACK (acknowledge)

收到通知

0000 0111

07

7

0x07

BEL (bell)

響鈴

0000 1000

010

8

0x08

BS (backspace)

退格

0000 1001

011

9

0x09

HT (horizontal tab)

水平製表符

0000 1010

012

10

0x0A

LF (NL line feed, new line)

換行鍵

0000 1011

013

11

0x0B

VT (vertical tab)

垂直製表符

0000 1100

014

12

0x0C

FF (NP form feed, new page)

換頁鍵

0000 1101

015

13

0x0D

CR (carriage return)

回車鍵

0000 1110

016

14

0x0E

SO (shift out)

不用切換

0000 1111

017

15

0x0F

SI (shift in)

啓用切換

0001 0000

020

16

0x10

DLE (data link escape)

數據鏈路轉義

0001 0001

021

17

0x11

DC1 (device control 1)

設備控制1

0001 0010

022

18

0x12

DC2 (device control 2)

設備控制2

0001 0011

023

19

0x13

DC3 (device control 3)

設備控制3

0001 0100

024

20

0x14

DC4 (device control 4)

設備控制4

0001 0101

025

21

0x15

NAK (negative acknowledge)

拒絕接收

0001 0110

026

22

0x16

SYN (synchronous idle)

同步空閒

0001 0111

027

23

0x17

ETB (end of trans. block)

結束傳輸塊

0001 1000

030

24

0x18

CAN (cancel)

取消

0001 1001

031

25

0x19

EM (end of medium)

媒介結束

0001 1010

032

26

0x1A

SUB (substitute)

代替

0001 1011

033

27

0x1B

ESC (escape)

換碼(溢出)

0001 1100

034

28

0x1C

FS (file separator)

文件分隔符

0001 1101

035

29

0x1D

GS (group separator)

分組符

0001 1110

036

30

0x1E

RS (record separator)

記錄分隔符

0001 1111

037

31

0x1F

US (unit separator)

單元分隔符

0010 0000

040

32

0x20

(space)

空格

0010 0001

041

33

0x21

!

歎號

0010 0010

042

34

0x22

"

雙引號

0010 0011

043

35

0x23

#

井號

0010 0100

044

36

0x24

$

美圓符

0010 0101

045

37

0x25

%

百分號

0010 0110

046

38

0x26

&

和號

0010 0111

047

39

0x27

'

閉單引號

0010 1000

050

40

0x28

(

開括號

0010 1001

051

41

0x29

)

閉括號

0010 1010

052

42

0x2A

*

星號

0010 1011

053

43

0x2B

+

加號

0010 1100

054

44

0x2C

,

逗號

0010 1101

055

45

0x2D

-

減號/破折號

0010 1110

056

46

0x2E

.

句號

0010 1111

057

47

0x2F

/

斜槓

0011 0000

060

48

0x30

0

字符0

0011 0001

061

49

0x31

1

字符1

0011 0010

062

50

0x32

2

字符2

0011 0011

063

51

0x33

3

字符3

0011 0100

064

52

0x34

4

字符4

0011 0101

065

53

0x35

5

字符5

0011 0110

066

54

0x36

6

字符6

0011 0111

067

55

0x37

7

字符7

0011 1000

070

56

0x38

8

字符8

0011 1001

071

57

0x39

9

字符9

0011 1010

072

58

0x3A

:

冒號

0011 1011

073

59

0x3B

;

分號

0011 1100

074

60

0x3C

<

小於

0011 1101

075

61

0x3D

=

等號

0011 1110

076

62

0x3E

>

大於

0011 1111

077

63

0x3F

?

問號

0100 0000

0100

64

0x40

@

電子郵件符號

0100 0001

0101

65

0x41

A

大寫字母A

0100 0010

0102

66

0x42

B

大寫字母B

0100 0011

0103

67

0x43

C

大寫字母C

0100 0100

0104

68

0x44

D

大寫字母D

0100 0101

0105

69

0x45

E

大寫字母E

0100 0110

0106

70

0x46

F

大寫字母F

0100 0111

0107

71

0x47

G

大寫字母G

0100 1000

0110

72

0x48

H

大寫字母H

0100 1001

0111

73

0x49

I

大寫字母I

01001010

0112

74

0x4A

J

大寫字母J

0100 1011

0113

75

0x4B

K

大寫字母K

0100 1100

0114

76

0x4C

L

大寫字母L

0100 1101

0115

77

0x4D

M

大寫字母M

0100 1110

0116

78

0x4E

N

大寫字母N

0100 1111

0117

79

0x4F

O

大寫字母O

0101 0000

0120

80

0x50

P

大寫字母P

0101 0001

0121

81

0x51

Q

大寫字母Q

0101 0010

0122

82

0x52

R

大寫字母R

0101 0011

0123

83

0x53

S

大寫字母S

0101 0100

0124

84

0x54

T

大寫字母T

0101 0101

0125

85

0x55

U

大寫字母U

0101 0110

0126

86

0x56

V

大寫字母V

0101 0111

0127

87

0x57

W

大寫字母W

0101 1000

0130

88

0x58

X

大寫字母X

0101 1001

0131

89

0x59

Y

大寫字母Y

0101 1010

0132

90

0x5A

Z

大寫字母Z

0101 1011

0133

91

0x5B

[

開方括號

0101 1100

0134

92

0x5C

\

反斜槓

0101 1101

0135

93

0x5D

]

閉方括號

0101 1110

0136

94

0x5E

^

脫字符

0101 1111

0137

95

0x5F

_

下劃線

0110 0000

0140

96

0x60

`

開單引號

0110 0001

0141

97

0x61

a

小寫字母a

0110 0010

0142

98

0x62

b

小寫字母b

0110 0011

0143

99

0x63

c

小寫字母c

0110 0100

0144

100

0x64

d

小寫字母d

0110 0101

0145

101

0x65

e

小寫字母e

0110 0110

0146

102

0x66

f

小寫字母f

0110 0111

0147

103

0x67

g

小寫字母g

0110 1000

0150

104

0x68

h

小寫字母h

0110 1001

0151

105

0x69

i

小寫字母i

0110 1010

0152

106

0x6A

j

小寫字母j

0110 1011

0153

107

0x6B

k

小寫字母k

0110 1100

0154

108

0x6C

l

小寫字母l

0110 1101

0155

109

0x6D

m

小寫字母m

0110 1110

0156

110

0x6E

n

小寫字母n

0110 1111

0157

111

0x6F

o

小寫字母o

0111 0000

0160

112

0x70

p

小寫字母p

0111 0001

0161

113

0x71

q

小寫字母q

0111 0010

0162

114

0x72

r

小寫字母r

0111 0011

0163

115

0x73

s

小寫字母s

0111 0100

0164

116

0x74

t

小寫字母t

0111 0101

0165

117

0x75

u

小寫字母u

0111 0110

0166

118

0x76

v

小寫字母v

0111 0111

0167

119

0x77

w

小寫字母w

0111 1000

0170

120

0x78

x

小寫字母x

0111 1001

0171

121

0x79

y

小寫字母y

0111 1010

0172

122

0x7A

z

小寫字母z

0111 1011

0173

123

0x7B

{

開花括號

0111 1100

0174

124

0x7C

|

垂線

0111 1101

0175

125

0x7D

}

閉花括號

0111 1110

0176

126

0x7E

~

波浪號

0111 1111

0177

127

0x7F

DEL (delete)

刪除

相關文章
相關標籤/搜索