計(jì)算機(jī)存儲(chǔ)的幾個(gè)概念
想要徹底搞清楚編碼問(wèn)題,我們必須要先搞清楚計(jì)算機(jī)是怎么存儲(chǔ)數(shù)據(jù)的皇拣,這就涉及到了計(jì)算機(jī)基礎(chǔ)的幾個(gè)概念了严蓖,開(kāi)篇我們就先來(lái)捋捋這幾個(gè)容易混淆的概念。
bit
二進(jìn)制位审磁, 是計(jì)算機(jī)內(nèi)部數(shù)據(jù)儲(chǔ)存的最小單位谈飒,11010100是一個(gè)8位二進(jìn)制數(shù)。一個(gè)二進(jìn)制位只可以表示0和1兩種狀態(tài)(21)态蒂;兩個(gè)二進(jìn)制位可以表示00杭措、01、10钾恢、11四種(22)狀態(tài)手素;三位二進(jìn)制數(shù)可表示八種狀態(tài)(2^3)……
Byte
字節(jié),是計(jì)算機(jī)中數(shù)據(jù)處理的基本單位瘩蚪,計(jì)算機(jī)中以字節(jié)為單位存儲(chǔ)和解釋信息泉懦,規(guī)定一個(gè)字節(jié)由八個(gè)二進(jìn)制位構(gòu)成,即1個(gè)字節(jié)等于8個(gè)比特(1Byte=8bit)疹瘦。八位二進(jìn)制數(shù)最小為00000000崩哩,最大為11111111;通常1個(gè)字節(jié)可以存入一個(gè)ASCII碼言沐,2個(gè)字節(jié)可以存放一個(gè)漢字國(guó)標(biāo)碼邓嘹。
字
在計(jì)算機(jī)中,一串?dāng)?shù)碼作為一個(gè)整體來(lái)處理或運(yùn)算的险胰,稱(chēng)為一個(gè)計(jì)算機(jī)字汹押,簡(jiǎn)稱(chēng)宇。字通常分為若干個(gè)字節(jié)(每個(gè)字節(jié)一般是8位)起便。在存儲(chǔ)器中棚贾,通常每個(gè)單元存儲(chǔ)一個(gè)字,因此每個(gè)字都是可以尋址的榆综。字的長(zhǎng)度用位數(shù)來(lái)表示妙痹。在計(jì)算機(jī)的運(yùn)算器鼻疮、控制器中,通常都是以字為單位進(jìn)行傳送的陋守。
字長(zhǎng)
字長(zhǎng):電腦技術(shù)中對(duì)CPU在單位時(shí)間內(nèi)(同一時(shí)間)能一次處理的二進(jìn)制數(shù)的位數(shù)叫字長(zhǎng)利赋。所以能處理字長(zhǎng)為8位數(shù)據(jù)的CPU通常就叫8位的CPU。同理32位的CPU就能在單位時(shí)間內(nèi)處理字長(zhǎng)為32位的二進(jìn)制數(shù)據(jù)猩系。
字節(jié)和字長(zhǎng)的區(qū)別:由于常用的英文字符用8位二進(jìn)制就可以表示媚送,所以通常就將8位稱(chēng)為一個(gè)字節(jié)寇甸。字長(zhǎng)的長(zhǎng)度是不固定的,對(duì)于不同的CPU拿霉、字長(zhǎng)的長(zhǎng)度也不一樣吟秩。8位的CPU一次只能處理一個(gè)字節(jié),而32位的CPU一次就能處理4個(gè)字節(jié)绽淘,同理字長(zhǎng)為64位的CPU一次可以處理8個(gè)字節(jié)涵防。
常見(jiàn)的編碼
ASCII
: 1個(gè)字節(jié)沪铭,只編碼英文字母和符號(hào)
gb2312
: 2個(gè)字節(jié),增加了中文漢字和符號(hào)
Unicode
: 把所有語(yǔ)言都統(tǒng)一到一套編碼里把所有語(yǔ)言都統(tǒng)一到一套編碼里杀怠,
一般是2個(gè)字節(jié),生僻字4個(gè)字節(jié)
utf-8
: 可變長(zhǎng)編碼橙依,常用的英文字母被編碼成1個(gè)字節(jié)硕旗,漢字通常是3個(gè)字節(jié)窗骑,只有很生僻的字符才會(huì)被編碼成4-6個(gè)字節(jié)卵渴。如果你要傳輸?shù)奈谋景罅坑⑽淖址鹬瘢肬TF-8編碼就能節(jié)省空間:
在計(jì)算機(jī)內(nèi)存中,統(tǒng)一使用Unicode編碼碘橘,當(dāng)需要保存到硬盤(pán)或者需要傳輸?shù)臅r(shí)候吱肌,就轉(zhuǎn)換為UTF-8編碼痘拆,這樣可以節(jié)省很多存儲(chǔ)空間氮墨。
Python編碼
注:這里討論的是python2.7的情況
兩個(gè)函數(shù)
在python中吐葵,str和unicode都是basestring的子類(lèi)桥氏,basestring有以下兩個(gè)方法:
encode()
: 將unicode字符串轉(zhuǎn)換為其他編碼字符串,參數(shù)為轉(zhuǎn)換后編碼
decode()
: 將其他編碼轉(zhuǎn)換為unicode字符串凤藏,參數(shù)為轉(zhuǎn)換前編碼
PS:"string".decode('utf-8') == unicode('string', 'utf-8')
一個(gè)栗子
s = '中文'
print type(s), len(s)
u = u'中文'
print type(u), len(u)
u2s = u'中文'.encode('utf-8')
print type(u2s), len(u2s)
結(jié)果是這樣的
<type 'str'> 6
<type 'unicode'> 2
<type 'str'> 6
console下查看u2s
>>> u'中文'.encode('utf-8')
'\xe4\xb8\xad\xe6\x96\x87'
結(jié)論:
- python中定義的一個(gè)str變量實(shí)則是字節(jié)串,由Unicode經(jīng)過(guò)編碼(encode)后的字節(jié)組成的(
也正好印證了utf8編碼中一個(gè)中文字符是3個(gè)字節(jié)) - Unicode才是真正意義上的字符串揖庄,由字符組成
再次回顧兩個(gè)函數(shù)用法
s = '中文'
# 這時(shí)是str欠雌,轉(zhuǎn)為unicode需要用decode
u = s.decode('utf-8')
print type(u)
# 打印 <type 'unicode'>
# unicode轉(zhuǎn)為str ,使用encode
s2 = u.encode('utf-8')
print type(s2)
# 打印 <type 'str'>
新結(jié)論:不同編碼轉(zhuǎn)換,使用Unicode作為中間編碼
#s是code_A的str
s.decode('code_A').encode('code_B')
在Python 3.x版本中,把'xxx'
和u'xxx'
已經(jīng)都統(tǒng)一成Unicode編碼了桨昙,即寫(xiě)不寫(xiě)前綴u都是一樣的,而以字節(jié)形式表示的字符串則必須加上b前綴:b'xxx'
齐苛。
由于Python源代碼也是一個(gè)文本文件桂塞,所以,當(dāng)你的源代碼中包含中文的時(shí)候阁危,在保存源代碼時(shí),就需要?jiǎng)?wù)必指定保存為UTF-8編碼擂煞。當(dāng)Python解釋器讀取源代碼時(shí)趴乡,為了讓它按UTF-8編碼讀取,我們通常在文件開(kāi)頭寫(xiě)上這兩行:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
參考
字節(jié)晾捏、字、位劳秋、比特,這四者之間的關(guān)系
廖雪峰:python2.7教程之字符串和編碼
PYTHON-進(jìn)階-編碼處理小結(jié)