0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從5個(gè)方面來解析計(jì)算機(jī)中的字符編碼概念

馬哥Linux運(yùn)維 ? 2018-01-16 09:08 ? 次閱讀

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

基本概念

常見字符編碼簡介

Python 的默認(rèn)編碼

Python2 中的字符類型

UnicodeEncodeError & UnicodeDecodeError 根源

基本概念

字符(Character)

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

字符集(Character set)

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

字符編碼(Character encoding)

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

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

從5個(gè)方面來解析計(jì)算機(jī)中的字符編碼概念

常見字符編碼簡介

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

ASCII

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

在 20 世紀(jì) 60 年代,美國制定了一套字符編碼方案,規(guī)定了英文字母,數(shù)字和一些普通符號跟二進(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ù)倪^程中就會出現(xiàn)各種各樣的亂碼(mojibake),這無疑是個(gè)災(zāi)難。

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

Unicode 1.0 版誕生于 1991 年 10 月,至今它仍在不斷增修,每個(gè)新版本都會加入更多新的字符,目前最新的版本為 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。更多的符號對應(yīng)表,可以查詢 unicode.org,或者專門的漢字對應(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è)漢字,但是對于其他的字符,就可能需要三個(gè)或四個(gè)字節(jié),甚至更多。

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

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

UTF-8 (8-bit Unicode Transformation Format) 是一種針對 Unicode 的可變長度字符編碼,它使用一到四個(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

Python2.7.11(default,Feb242016,10:48:05)

[GCC4.2.1Compatible AppleLLVM7.0.2(clang-700.1.81)]on darwin

Type"help","copyright","credits"or"license"formoreinformation.

>>>importsys

>>>sys.getdefaultencoding()

'ascii'

Python3

Python3.5.2(default,Jun292016,13:43:58)

[GCC4.2.1Compatible AppleLLVM7.3.0(clang-703.0.31)]on darwin

Type"help","copyright","credits"or"license"formoreinformation.

>>>importsys

>>>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'中文'

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

>>>u'中文'.encode('utf-8')

'??-???'

UnicodeEncodeError & UnicodeDecodeError 根源

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

下面有兩個(gè)常見的場景,我們最好牢牢記?。?/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# 會進(jìn)行隱式轉(zhuǎn)換,即 s.decode('ascii') + u

Traceback(most recent calllast):

File"",line1,in

UnicodeDecodeError:'ascii'codeccan'tdecodebyte0xe4inposition0:ordinalnotinrange(128)

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

>>>s='你好'# str 類型,utf-8 編碼

>>>u=u'世界'

>>>

>>>s.decode('utf-8')+u# 顯示指定 'utf-8' 進(jìn)行轉(zhuǎn)換

u'你好世界'# 注意這不是錯(cuò)誤,這是 unicode 字符串

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

讓我們看看例子:

>>>u_str=u'你好'

>>>str(u_str)

Traceback(most recent calllast):

File"",line1,in

UnicodeEncodeError:'ascii'codeccan'tencode charactersinposition0-1:ordinalnotinrange(128)

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

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

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

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

>>>name=raw_input('input your name: ')

inputyourname:ethan

>>>name

'ethan'

>>>name=raw_input('輸入你的姓名:')

輸入你的姓名:小明

>>>name

'?°????'

>>>type(name)

>>>name=raw_input(u'輸入你的姓名: ')# 會試圖使用 u'輸入你的姓名'.encode('ascii')

Traceback(most recent calllast):

File"",line1,in

UnicodeEncodeError:'ascii'codeccan'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'你好'

printhello

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

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

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

hello=u'你好'

printhello.encode('utf-8')

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

小結(jié)

UTF-8 是一種針對 Unicode 的可變長度字符編碼,它是 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ù)或類等對象接收的是 str 類型的字符串,但你傳的是 unicode,Python2 會默認(rèn)使用 ascii 將其編碼成 str 類型再運(yùn)算。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 計(jì)算機(jī)
    +關(guān)注

    關(guān)注

    19

    文章

    7168

    瀏覽量

    87149
  • 編碼
    +關(guān)注

    關(guān)注

    6

    文章

    915

    瀏覽量

    54651
  • 字符
    +關(guān)注

    關(guān)注

    0

    文章

    230

    瀏覽量

    25106
  • python
    +關(guān)注

    關(guān)注

    53

    文章

    4753

    瀏覽量

    84076

原文標(biāo)題:Python字符編碼全解析

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    計(jì)算機(jī)中的電磁兼容情況

    電磁兼容的英文名稱為Electromagnetic Compatibility ,簡稱EMC。電磁兼容技術(shù)涉及的頻率范圍寬達(dá)0-400GHz,研究對象除傳統(tǒng)設(shè)施外,涉及芯片級,直到各型艦船、航天飛機(jī)、洲際導(dǎo)彈,甚至整個(gè)地球的電磁環(huán)境。本文章主要介紹計(jì)算機(jī)中的電磁兼容情況。
    發(fā)表于 05-31 08:22

    8086微型計(jì)算機(jī)常用字符編碼

    ?8086微型計(jì)算機(jī)常用字符編碼,深圳大學(xué)2016博士研究生招生微機(jī)原理考試大綱命題學(xué)院/部門(蓋章):光電工程學(xué)院考試科目代碼及名稱:2225微機(jī)原理一、考試基本要求《微機(jī)原理》是理工科計(jì)算
    發(fā)表于 07-16 08:28

    什么是計(jì)算機(jī)系統(tǒng)、計(jì)算機(jī)硬件和計(jì)算機(jī)軟件?

    第一章 計(jì)算機(jī)系統(tǒng)概論1. 什么是計(jì)算機(jī)系統(tǒng)、計(jì)算機(jī)硬件和計(jì)算機(jī)軟件?硬件和軟件哪個(gè)更重要?解:P3計(jì)算機(jī)系統(tǒng):由
    發(fā)表于 07-22 09:06

    計(jì)算機(jī)中不同硬件對Hz的定義相同嗎

    Hz(赫茲)通常的定義是波形每秒鐘變化或振動(dòng)的次數(shù),在計(jì)算機(jī)中不同硬件對Hz的定義各不相同。CPU:Hz用來表示時(shí)鐘頻率。目前的CPU通常以MHz和GHz作為計(jì)量單位。顯示器:在顯示器中有三個(gè)頻率
    發(fā)表于 09-08 06:10

    微型計(jì)算機(jī)中采用的邏輯元件是什么

    第7部分 計(jì)算機(jī)硬件 單選(1) .[B]計(jì)算機(jī)向使用者傳送計(jì)算、處理結(jié)果的設(shè)備稱為______。(A) 輸入設(shè)備(B) 輸出設(shè)備(C) 存儲設(shè)備(D) 微處理器(2) .[C]目前微型計(jì)算機(jī)
    發(fā)表于 09-15 07:43

    基于嵌入式實(shí)時(shí)軟件在計(jì)算機(jī)中的應(yīng)用研究

    以及應(yīng)用前景四方面探究了它在計(jì)算機(jī)中的有效應(yīng)用,針對應(yīng)用內(nèi)容進(jìn)行了詳細(xì)探討。關(guān)鍵詞:嵌入式實(shí)時(shí)軟件計(jì)算機(jī)引言新時(shí)代,計(jì)算機(jī)普及應(yīng)用于各個(gè)領(lǐng)域,同時(shí)成為了人們?nèi)粘I畈豢苫蛉钡闹匾ぞ摺?/div>
    發(fā)表于 11-09 07:05

    個(gè)人計(jì)算機(jī)中的串行端

    【LabVIEW入門到精通】4.1.5 個(gè)人計(jì)算機(jī)中的串行端口
    發(fā)表于 01-08 15:43 ?0次下載

    計(jì)算機(jī)的數(shù)制及其轉(zhuǎn)換_微控制器原理及應(yīng)用

    計(jì)算機(jī)的最基本功能是進(jìn)行數(shù)據(jù)的計(jì)算和處理加工。計(jì)算機(jī)中的數(shù)是以器件的兩個(gè)不同物理狀態(tài)表示的,一個(gè)
    發(fā)表于 05-12 14:25 ?0次下載

    量子計(jì)算機(jī)的優(yōu)點(diǎn)_量子計(jì)算機(jī)的應(yīng)用_量子計(jì)算機(jī)的未來應(yīng)用

    量子計(jì)算機(jī)是一類遵循量子力學(xué)規(guī)律進(jìn)行高速數(shù)學(xué)和邏輯運(yùn)算、存儲及處理量子信息的物理裝置。當(dāng)某個(gè)裝置處理和計(jì)算的是量子信息,運(yùn)行的是量子算法時(shí),它就是量子計(jì)算機(jī)。量子計(jì)算機(jī)
    發(fā)表于 11-28 18:10 ?1.2w次閱讀

    計(jì)算機(jī)中的圖像(Image)和圖形(Graphic)

    計(jì)算機(jī)中的圖形(Graphic)和圖像(Image) demi 在 周三, 03/27/2019 - 11:39 提交 在計(jì)算機(jī)中處理的圖像是經(jīng)過”數(shù)字化”后的視覺圖像,稱為數(shù)字化圖像 圖像
    的頭像 發(fā)表于 03-25 10:03 ?2.7w次閱讀
    <b class='flag-5'>計(jì)算機(jī)中</b>的圖像(Image)和圖形(Graphic)

    計(jì)算機(jī)編碼解析

    你是不是工作了很多年了,一直沒搞清楚計(jì)算機(jī)中的各種編碼規(guī)則,雖然平時(shí)都會使用,但是內(nèi)部機(jī)制原理一直都是之其然而不知其所以然,開發(fā)也會經(jīng)常涉及到這塊內(nèi)容,但都沒有太多重視,這可能會讓有吃一些虧(出項(xiàng)目bug了),本著追本溯源的精
    的頭像 發(fā)表于 03-30 10:28 ?1079次閱讀
    <b class='flag-5'>計(jì)算機(jī)</b><b class='flag-5'>編碼</b>全<b class='flag-5'>解析</b>(<b class='flag-5'>中</b>)

    cmos技術(shù)在計(jì)算機(jī)中的應(yīng)用

    降低,速度提高,傳輸距離延長,從而在計(jì)算機(jī)領(lǐng)域有著廣泛的應(yīng)用。本文將詳細(xì)介紹CMOS技術(shù)在計(jì)算機(jī)中的應(yīng)用。 1. CPU CPU是計(jì)算機(jī)中最重要的核心部件。CMOS技術(shù)在CPU上的應(yīng)用,使得CPU的性能得到了巨大的提升。CMOS
    的頭像 發(fā)表于 09-05 17:39 ?1416次閱讀

    DRAM在計(jì)算機(jī)中的應(yīng)用

    DRAM(Dynamic Random Access Memory,動(dòng)態(tài)隨機(jī)存取存儲器)在計(jì)算機(jī)系統(tǒng)扮演著至關(guān)重要的角色。它是一種半導(dǎo)體存儲器,用于存儲和快速訪問數(shù)據(jù),是計(jì)算機(jī)主內(nèi)存的主要組成部分。以下是對DRAM在
    的頭像 發(fā)表于 07-24 17:04 ?449次閱讀

    邊沿觸發(fā)器在計(jì)算機(jī)中的應(yīng)用

    邊沿觸發(fā)器在計(jì)算機(jī)中的應(yīng)用極為廣泛,它們作為數(shù)字電路的基本單元,對于實(shí)現(xiàn)計(jì)算機(jī)內(nèi)部的時(shí)序控制、數(shù)據(jù)存儲與傳輸、以及復(fù)雜邏輯功能等方面起著至關(guān)重要的作用。以下將從邊沿觸發(fā)器的定義、特點(diǎn)
    的頭像 發(fā)表于 08-12 14:20 ?171次閱讀

    計(jì)算機(jī)中總線的作用是什么

    計(jì)算機(jī)中,總線(Bus)扮演著極其重要的角色,它是計(jì)算機(jī)內(nèi)部各功能部件之間傳送信息的公共通信干線??偩€不僅連接了計(jì)算機(jī)的各個(gè)核心組件,還確保了數(shù)據(jù)、指令和控制信號的高效、準(zhǔn)確傳輸。
    的頭像 發(fā)表于 08-26 15:57 ?210次閱讀