成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Python: 熟悉又陌生的字符編碼

Vultr / 566人閱讀

摘要:常見的字符編碼有編碼,編碼,編碼等。碼只規(guī)定了個(gè)字符的編碼,這在美國是夠用的。小結(jié)是一種針對(duì)的可變長(zhǎng)度字符編碼,它是的實(shí)現(xiàn)方式之一。

字符編碼是計(jì)算機(jī)編程中不可回避的問題,不管你用 Python2 還是 Python3,亦或是 C++, Java 等,我都覺得非常有必要厘清計(jì)算機(jī)中的字符編碼概念。本文主要分以下幾個(gè)部分介紹:

基本概念

常見字符編碼簡(jiǎn)介

Python 的默認(rèn)編碼

Python2 中的字符類型

UnicodeEncodeError & UnicodeDecodeError 根源

基本概念

字符(Character)

在電腦和電信領(lǐng)域中,字符是一個(gè)信息單位,它是各種文字和符號(hào)的總稱,包括各國家文字、標(biāo)點(diǎn)符號(hào)、圖形符號(hào)、數(shù)字等。比如,一個(gè)漢字,一個(gè)英文字母,一個(gè)標(biāo)點(diǎn)符號(hào)等都是一個(gè)字符。

字符集(Character set)

字符集是字符的集合。字符集的種類較多,每個(gè)字符集包含的字符個(gè)數(shù)也不同。比如,常見的字符集有 ASCII 字符集、GB2312 字符集、Unicode 字符集等,其中,ASCII 字符集共有 128 個(gè)字符,包含可顯示字符(比如英文大小寫字符、阿拉伯?dāng)?shù)字)和控制字符(比如空格鍵、回車鍵);GB2312 字符集是中國國家標(biāo)準(zhǔn)的簡(jiǎn)體中文字符集,包含簡(jiǎn)化漢字、一般符號(hào)、數(shù)字等;Unicode 字符集則包含了世界各國語言中使用到的所有字符,

字符編碼(Character encoding)

字符編碼,是指對(duì)于字符集中的字符,將其編碼為特定的二進(jìn)制數(shù),以便計(jì)算機(jī)處理。常見的字符編碼有 ASCII 編碼,UTF-8 編碼,GBK 編碼等。一般而言,字符集字符編碼往往被認(rèn)為是同義的概念,比如,對(duì)于字符集 ASCII,它除了有「字符的集合」這層含義外,同時(shí)也包含了「編碼」的含義,也就是說,ASCII 既表示了字符集也表示了對(duì)應(yīng)的字符編碼。

下面我們用一個(gè)表格做下總結(jié):

概念 概念描述 舉例
字符 一個(gè)信息單位,各種文字和符號(hào)的總稱 ‘中’, ‘a(chǎn)", ‘1", "$", ‘¥’, ...?
字符集 字符的集合 ASCII 字符集, GB2312 字符集, Unicode 字符集
字符編碼 將字符集中的字符,編碼為特定的二進(jìn)制數(shù) ASCII 編碼,GB2312 編碼,Unicode 編碼
字節(jié) 計(jì)算機(jī)中存儲(chǔ)數(shù)據(jù)的單元,一個(gè) 8 位(bit)的二進(jìn)制數(shù) 0x01, 0x45, ...
常見字符編碼簡(jiǎn)介

常見的字符編碼有 ASCII 編碼,GBK 編碼,Unicode 編碼和 UTF-8 編碼等等。這里,我們主要介紹 ASCII、Unicode 和 UTF-8。

ASCII

計(jì)算機(jī)是在美國誕生的,人家用的是英語,而在英語的世界里,不過就是英文字母,數(shù)字和一些普通符號(hào)的組合而已。

在 20 世紀(jì) 60 年代,美國制定了一套字符編碼方案,規(guī)定了英文字母,數(shù)字和一些普通符號(hào)跟二進(jìn)制的轉(zhuǎn)換關(guān)系,被稱為 ASCII (American Standard Code for Information Interchange,美國信息互換標(biāo)準(zhǔn)編碼) 碼。

比如,大寫英文字母 A 的二進(jìn)制表示是 01000001(十進(jìn)制 65),小寫英文字母 a 的二進(jìn)制表示是 01100001 (十進(jìn)制 97),空格 SPACE 的二進(jìn)制表示是 00100000(十進(jìn)制 32)。

Unicode

ASCII 碼只規(guī)定了 128 個(gè)字符的編碼,這在美國是夠用的??墒?,計(jì)算機(jī)后來傳到了歐洲,亞洲,乃至世界各地,而世界各國的語言幾乎是完全不一樣的,用 ASCII 碼來表示其他語言是遠(yuǎn)遠(yuǎn)不夠的,所以,不同的國家和地區(qū)又制定了自己的編碼方案,比如中國大陸的 GB2312 編碼 和 GBK 編碼等,日本的 Shift_JIS 編碼等等。

雖然各個(gè)國家和地區(qū)可以制定自己的編碼方案,但不同國家和地區(qū)的計(jì)算機(jī)在數(shù)據(jù)傳輸?shù)倪^程中就會(huì)出現(xiàn)各種各樣的亂碼(mojibake),這無疑是個(gè)災(zāi)難。

怎么辦?想法也很簡(jiǎn)單,就是將全世界所有的語言統(tǒng)一成一套編碼方案,這套編碼方案就叫 Unicode,它為每種語言的每個(gè)字符設(shè)定了獨(dú)一無二的二進(jìn)制編碼,這樣就可以跨語言,跨平臺(tái)進(jìn)行文本處理了,是不是很棒!

Unicode 1.0 版誕生于 1991 年 10 月,至今它仍在不斷增修,每個(gè)新版本都會(huì)加入更多新的字符,目前最新的版本為 2016 年 6 月 21 日公布的 9.0.0。

Unicode 標(biāo)準(zhǔn)使用十六進(jìn)制數(shù)字,而且在數(shù)字前面加上前綴 U+,比如,大寫字母「A」的 unicode 編碼為 U+0041,漢字「嚴(yán)」的 unicode 編碼為 U+4E25。更多的符號(hào)對(duì)應(yīng)表,可以查詢 unicode.org,或者專門的漢字對(duì)應(yīng)表。

UTF-8

Unicode 看起來已經(jīng)很完美了,實(shí)現(xiàn)了大一統(tǒng)。但是,Unicode 卻存在一個(gè)很大的問題:資源浪費(fèi)。

為什么這么說呢?原來,Unicode 為了能表示世界各國所有文字,一開始用兩個(gè)字節(jié),后來發(fā)現(xiàn)兩個(gè)字節(jié)不夠用,又用了四個(gè)字節(jié)。比如,漢字「嚴(yán)」的 unicode 編碼是十六進(jìn)制數(shù) 4E25,轉(zhuǎn)換成二進(jìn)制有十五位,即 100111000100101,因此至少需要兩個(gè)字節(jié)才能表示這個(gè)漢字,但是對(duì)于其他的字符,就可能需要三個(gè)或四個(gè)字節(jié),甚至更多。

這時(shí),問題就來了,如果以前的 ASCII 字符集也用這種方式來表示,那豈不是很浪費(fèi)存儲(chǔ)空間。比如,大寫字母「A」的二進(jìn)制編碼為 01000001,它只需要一個(gè)字節(jié)就夠了,如果 unicode 統(tǒng)一使用三個(gè)字節(jié)或四個(gè)字節(jié)來表示字符,那「A」的二進(jìn)制編碼的前面幾個(gè)字節(jié)就都是 0,這是很浪費(fèi)存儲(chǔ)空間的。

為了解決這個(gè)問題,在 Unicode 的基礎(chǔ)上,人們實(shí)現(xiàn)了 UTF-16, UTF-32 和 UTF-8。下面只說一下 UTF-8。

UTF-8 (8-bit Unicode Transformation Format) 是一種針對(duì) Unicode 的可變長(zhǎng)度字符編碼,它使用一到四個(gè)字節(jié)來表示字符,例如,ASCII 字符繼續(xù)使用一個(gè)字節(jié)編碼,阿拉伯文、希臘文等使用兩個(gè)字節(jié)編碼,常用漢字使用三個(gè)字節(jié)編碼,等等。

因此,我們說,UTF-8 是 Unicode 的實(shí)現(xiàn)方式之一,其他實(shí)現(xiàn)方式還包括 UTF-16(字符用兩個(gè)或四個(gè)字節(jié)表示)和 UTF-32(字符用四個(gè)字節(jié)表示)。

Python 的默認(rèn)編碼

Python2 的默認(rèn)編碼是 ascii,Python3 的默認(rèn)編碼是 utf-8,可以通過下面的方式獲?。?/p>

Python2

Python 2.7.11 (default, Feb 24 2016, 10:48:05)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getdefaultencoding()
"ascii"

Python3

Python 3.5.2 (default, Jun 29 2016, 13:43:58)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getdefaultencoding()
"utf-8"
Python2 中的字符類型

Python2 中有兩種和字符串相關(guān)的類型:str 和 unicode,它們的父類是 basestring。其中,str 類型的字符串有多種編碼方式,默認(rèn)是 ascii,還有 gbk,utf-8 等,unicode 類型的字符串使用 u"..." 的形式來表示,下面的圖展示了 str 和 unicode 之間的關(guān)系:

兩種字符串的相互轉(zhuǎn)換概括如下:

把 UTF-8 編碼表示的字符串 "xxx" 轉(zhuǎn)換為 Unicode 字符串 u"xxx" 用 decode("utf-8") 方法:

>>> "中文".decode("utf-8")
u"u4e2du6587"

把 u"xxx" 轉(zhuǎn)換為 UTF-8 編碼的 "xxx" 用 encode("utf-8") 方法:

>>> u"中文".encode("utf-8")
"xe4xb8xadxe6x96x87"
UnicodeEncodeError & UnicodeDecodeError 根源

用 Python2 編寫程序的時(shí)候經(jīng)常會(huì)遇到 UnicodeEncodeError 和 UnicodeDecodeError,它們出現(xiàn)的根源就是如果代碼里面混合使用了 str 類型和 unicode 類型的字符串,Python 會(huì)默認(rèn)使用 ascii 編碼嘗試對(duì) unicode 類型的字符串編碼 (encode),或?qū)?str 類型的字符串解碼 (decode),這時(shí)就很可能出現(xiàn)上述錯(cuò)誤。

下面有兩個(gè)常見的場(chǎng)景,我們最好牢牢記?。?/p>

在進(jìn)行同時(shí)包含 str 類型和 unicode 類型的字符串操作時(shí),Python2 一律都把 str 解碼(decode)成 unicode 再運(yùn)算,這時(shí)就很容易出現(xiàn) UnicodeDecodeError。

讓我們看看例子:

>>> s = "你好"    # str 類型, utf-8 編碼
>>> u = u"世界"   # unicode 類型
>>> s + u        # 會(huì)進(jìn)行隱式轉(zhuǎn)換,即 s.decode("ascii") + u
Traceback (most recent call last):
  File "", line 1, in 
UnicodeDecodeError: "ascii" codec can"t decode byte 0xe4 in position 0: ordinal not in range(128)

為了避免出錯(cuò),我們就需要顯示指定使用 "utf-8" 進(jìn)行解碼,如下:

>>> s = "你好"                 # str 類型,utf-8 編碼
>>> u = u"世界"
>>>
>>> s.decode("utf-8") + u     # 顯示指定 "utf-8" 進(jìn)行轉(zhuǎn)換
u"u4f60u597du4e16u754c"   # 注意這不是錯(cuò)誤,這是 unicode 字符串

如果函數(shù)或類等對(duì)象接收的是 str 類型的字符串,但你傳的是 unicode,Python2 會(huì)默認(rèn)使用 ascii 將其編碼成 str 類型再運(yùn)算,這時(shí)就很容易出現(xiàn) UnicodeEncodeError。

讓我們看看例子:

>>> u_str = u"你好"
>>> str(u_str)
Traceback (most recent call last):
  File "", line 1, in 
UnicodeEncodeError: "ascii" codec can"t encode characters in position 0-1: ordinal not in range(128)

在上面的代碼中,u_str 是一個(gè) unicode 類型的字符串,由于 str() 的參數(shù)只能是 str 類型,此時(shí) Python 會(huì)試圖使用 ascii 將其編碼成 ascii,也就是:

u_str.encode("ascii")   // u_str 是 unicode 字符串

上面將 unicode 類型的中文使用 ascii 編碼轉(zhuǎn),肯定會(huì)出錯(cuò)。

再看一個(gè)使用 raw_input 的例子,注意 raw_input 只接收 str 類型的字符串:

>>> name = raw_input("input your name: ")
input your name: ethan
>>> name
"ethan"

>>> name = raw_input("輸入你的姓名:")
輸入你的姓名: 小明
>>> name
"xe5xb0x8fxe6x98x8e"
>>> type(name)


>>> name = raw_input(u"輸入你的姓名: ")   # 會(huì)試圖使用 u"輸入你的姓名".encode("ascii")
Traceback (most recent call last):
  File "", line 1, in 
UnicodeEncodeError: "ascii" codec can"t encode characters in position 0-5: ordinal not in range(128)

>>> name = raw_input(u"輸入你的姓名: ".encode("utf-8")) #可以,但此時(shí) name 不是 unicode 類型
輸入你的姓名: 小明
>>> name
"xe5xb0x8fxe6x98x8e"
>>> type(name)


>>> name = raw_input(u"輸入你的姓名: ".encode("utf-8")).decode("utf-8") # 推薦
輸入你的姓名:  小明
>>> name
u"u5c0fu660e"
>>> type(name)

再看一個(gè)重定向的例子:

hello = u"你好"
print hello

將上面的代碼保存到文件 hello.py,在終端執(zhí)行 python hello.py 可以正常打印,但是如果將其重定向到文件 python hello.py > result 會(huì)發(fā)現(xiàn) UnicodeEncodeError。

這是因?yàn)椋狠敵龅娇刂婆_(tái)時(shí),print 使用的是控制臺(tái)的默認(rèn)編碼,而重定向到文件時(shí),print 就不知道使用什么編碼了,于是就使用了默認(rèn)編碼 ascii 導(dǎo)致出現(xiàn)編碼錯(cuò)誤。

應(yīng)該改成如下:

hello = u"你好"
print hello.encode("utf-8")

這樣執(zhí)行 python hello.py > result 就沒有問題。

小結(jié)

UTF-8 是一種針對(duì) Unicode 的可變長(zhǎng)度字符編碼,它是 Unicode 的實(shí)現(xiàn)方式之一。

Unicode 字符集有多種編碼標(biāo)準(zhǔn),比如 UTF-8, UTF-7, UTF-16。

在進(jìn)行同時(shí)包含 str 類型和 unicode 類型的字符串操作時(shí),Python2 一律都把 str 解碼(decode)成 unicode 再運(yùn)算。

如果函數(shù)或類等對(duì)象接收的是 str 類型的字符串,但你傳的是 unicode,Python2 會(huì)默認(rèn)使用 ascii 將其編碼成 str 類型再運(yùn)算。

參考資料

字符 - 維基百科,自由的百科全書

UTF-8 - 維基百科,自由的百科全書

字符,字節(jié)和編碼 - Characters, Bytes And Encoding

字符編碼筆記:ASCII,Unicode和UTF-8 - 阮一峰的網(wǎng)絡(luò)日志

字符串和編碼 - 廖雪峰的官方網(wǎng)站

python - Dangers of sys.setdefaultencoding("utf-8") - Stack Overflow

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44316.html

相關(guān)文章

  • 談?wù)勎?em>熟悉陌生cookie

    摘要:前言大概是我的業(yè)務(wù)領(lǐng)域比較狹窄的原因我總是會(huì)聽說卻很少在實(shí)際的開發(fā)中應(yīng)用或者實(shí)踐過它今天剛好看到高級(jí)程序設(shè)計(jì)第三版的數(shù)據(jù)存儲(chǔ)部分說到了這里就對(duì)做一個(gè)深入訪談希望和我一樣對(duì)似曾相識(shí)的朋友可以真正的熟悉并學(xué)會(huì)利用來服務(wù)我們的業(yè)務(wù)定義是服務(wù)器為了 前言 大概是我的業(yè)務(wù)領(lǐng)域比較狹窄的原因,我總是會(huì)聽說cookie,卻很少在實(shí)際的開發(fā)中應(yīng)用或者實(shí)踐過它,今天剛好看到的數(shù)據(jù)存儲(chǔ)部分,說到了cook...

    fizz 評(píng)論0 收藏0
  • Python2.x 字符編碼終極指南

    摘要:值得注意的是,有的編碼方案不一定能表示某些信息,這時(shí)編碼就會(huì)失敗,比如就不能用來表示中文。數(shù)組的每一項(xiàng)是一個(gè)字節(jié),用來表示。所以對(duì)于字符串來說,其長(zhǎng)度等于編碼后字節(jié)的長(zhǎng)度。所以,讓來編碼解碼中文,就超出了其能力范圍。 在人機(jī)交互之字符編碼 一文中對(duì)字符編碼進(jìn)行了詳細(xì)的討論,并通過一些簡(jiǎn)單的小程序驗(yàn)證了我們對(duì)于字符編碼的認(rèn)識(shí)。但僅了解這篇文章的內(nèi)容,并不能幫我們?cè)谌粘>幊讨卸氵^一些字符編...

    Amio 評(píng)論0 收藏0
  • JS基礎(chǔ)篇--JS之表單提交時(shí)編碼類型enctype詳解

    摘要:格式支持比鍵值對(duì)復(fù)雜得多的結(jié)構(gòu)化數(shù)據(jù),這一點(diǎn)也很有用。例如下面這段代碼最終發(fā)送的請(qǐng)求是這種方案,可以方便的提交復(fù)雜的結(jié)構(gòu)化數(shù)據(jù),特別適合的接口。 簡(jiǎn)介 form的enctype屬性為編碼方式,常用有兩種:application/x-www-form-urlencoded和multipart/form-data,默認(rèn)為application/x-www-form-urlencoded。 ...

    ad6623 評(píng)論0 收藏0
  • Python: 陌生 metaclass

    摘要:但一般情況下,我們使用類作為元類。那么,元類到底有什么用呢要你何用元類的主要目的是為了控制類的創(chuàng)建行為。當(dāng)然,有很多種做法,這里展示用元類的做法。當(dāng)你創(chuàng)建類時(shí),解釋器會(huì)調(diào)用元類來生成它,定義一個(gè)繼承自的普通類意味著調(diào)用來創(chuàng)建它。 元類 Python 中的元類(metaclass)是一個(gè)深度魔法,平時(shí)我們可能比較少接觸到元類,本文將通過一些簡(jiǎn)單的例子來理解這個(gè)魔法。 類也是對(duì)象 在 Py...

    miya 評(píng)論0 收藏0
  • Python入門-基本語法1

    摘要:根據(jù)有效范圍作用域分為全局變量和局部變量。類型以開頭標(biāo)識(shí)類型以開頭標(biāo)識(shí)類型以進(jìn)制的字節(jié)碼表示,實(shí)際上是一個(gè)字節(jié)串,回應(yīng)了它的另一個(gè)名字。 < 返回索引頁 基本語法 Hello World 代碼注釋 關(guān)鍵字 數(shù)據(jù)類型 變量、常量 變量 變量賦值 變量命名 變量的作用域 常量 字符串與編碼 字符轉(zhuǎn)義 字符編碼 字符串操作 運(yùn)算符與表達(dá)式 運(yùn)算符 表達(dá)式 ...

    ingood 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

Vultr

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<