字符編碼
計算機只認識數字,咱們平時在使用計算機時,用的都是人類能讀懂的字符(用高級語言編程的結果也無非是在文件內寫了一堆字符),如何能讓計算機讀懂人類的字符?必須通過一個過程: 字符--------(翻譯過程)------->數字 這個過程實際就是一個字符如何對應一個特定數字的標準,這個標準稱之爲字符編碼node
1、存取文件的原理(nodepad++,pycharm,word)
- a、打開編輯器就打開了啓動了一個進程,是在內存中的,因此,用編輯器編寫的內容也都是存放與內存中的,斷電後數據丟失
- b、要想永久保存,須要點擊保存按鈕:編輯器把內存的數據刷到了硬盤上。
- c、在咱們編寫一個py文件(沒有執行),跟編寫其餘文件沒有任何區別,都只是在編寫一堆字符而已。
2、編碼發展
- 階段1:現代計算機起源於美國,最先誕生也是基於英文考慮的ASCII,ASCII:用1個字節Bytes(8位二進制)表明一個字符
- 階段2:爲了知足中文和英文,中國人定製了GBK, GBK:2Bytes表明一箇中文字符,1Bytes表示一個英文字符
- 階段3:各國有各國的標準,出現衝突,unicode出現了,可以兼容萬國字符。 unicode(定長):經常使用2個字節(16位二進制)表明一個字符,生僻字須要用4個字節
- 階段4:對於通篇都是英文的文原本說,unicode的式無疑是多了一倍的存儲空間(二進制最終都是以電或者磁的方式存儲到存儲介質中的)因而產生了UTF-8(可變長,全稱Unicode Transformation Format)UTF-8:對英文字符只用1Bytes表示,對中文字符用3Bytes,對其餘生僻字用更多的Bytes去存。
3、亂碼來源
- 亂碼1:存文件時就已經亂碼
- 存文件時,因爲文件內有各個國家的文字,咱們單以shiftjis去存, 本質上其餘國家的文字在shiftjis中沒有找到對應關係,不能存而硬存,確定是亂存了,即存文件階段就已經發生亂碼,而當咱們用shiftjis打開文件時,日文能夠正常顯示,而中文則亂碼了。
- 亂碼2:存文件時不亂碼而讀文件時亂碼【按照什麼標準編碼的,就要按照什麼標準解碼】
- 存文件時用utf-8編碼,保證兼容萬國,不會亂碼,而讀文件時選擇了錯誤的解碼方式,好比gbk,則在讀階段發生亂碼,讀階段發生亂碼是能夠解決的,選對正確的解碼方式就ok了,
4、特別說明
- 指定頭信息#-*-coding:utf-8-*- python解釋器編碼就是頭信息編碼, 沒有指定頭信息,那就使用默認的python2中默認使用ascii,python3中默認使用utf-8。
- 在python2中有兩種字符串類型str(編碼成文件頭指定的編碼格式)和unicode 在python3 中也有兩種字符串類型str(直接編碼成unicode)和bytes python2中的str類型就是python3的bytes類型
- 特別說明print時,open時,沒指定編碼格式就使用終端的編碼格式。
- sys.stdout.encoding,默認就是locale的編碼,print會用sys.stdout.encoding去encode()成字節流,交給terminal顯示。因此locale須要與terminal一致,才能正確print打印出中文。
- 瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換爲UTF-8再傳輸到瀏覽器
- 若是服務端encode的編碼格式是utf-8, 客戶端內存中收到的也是utf-8編碼的結果。
- *****內存中統一採用unicode,浪費空間來換取能夠轉換成任意編碼(不亂碼),硬盤能夠採用各類編碼,如utf-8,保證存放於硬盤或者基於網絡傳輸的數據量很小,提升傳輸效率與穩定性。*****
- ***在存入磁盤時,須要將unicode轉成一種更爲精準的格式,utf-8****
- ***在讀入內存時,須要將utf-8轉成unicode****
5、python解釋器執行py文件的3個階段
- 階段1:啓動python解釋器至關於啓動了一個文本編輯器
- 階段2:從硬盤讀取test.py文件內容到內存。【此時,python解釋器會讀取test.py的頭信息#-*-coding:utf-8-*-,來決定以什麼編碼格式讀入到內存,能夠用sys.getdefaultencoding()查看,若是沒有指定頭信息#-*-coding:utf-8-*-,那就使用python解釋器默認的編碼,python2中默認使用ascii,python3中默認使用utf-8。】
- 階段3:解釋執行階段。【在該階段,纔會識別python的語法,執行文件內代碼,當執行到name="tom"時,會開闢內存空間存放字符串"tom"。】
- python解釋器比文本編輯器多了階段3
細說階段3
- 在程序執行以前,內存中都是unicode
- 程序在執行過程當中,會申請內存(與程序代碼所存在的內存是倆個空間)用來存放python的數據類型的值,好比x="tom",會被python解釋器識別爲字符串,會申請內存空間來存放字符串類型的值,至於該字符串類型的值被識別成何種編碼存放,這就與python解釋器有關了,而python2與python3的字符串類型又有所不一樣。
- 在python2中有兩種字符串類型str(編碼成文件頭指定的編碼格式)和unicode
- 在python3中也有兩種字符串類型str(直接是unicode)和bytes (也就是python2中的str)
- 字節字符串和字符字符串
- (內存)unicode----->encode-------->utf-8(硬盤)
- (硬盤)utf-8----->decode-------->unicode(內存)
6、總結
- 字符按照什麼標準而編碼的,就要按照什麼標準解碼
- 在內存中寫的全部字符,一視同仁,都是unicode編碼,好比咱們打開編輯器,輸入一個「你」,咱們並不能說「你」就是一個漢字,此時它僅僅只是一個符號,該符號可能不少國家都在使用,根據咱們使用的輸入法不一樣這個字的樣式可能也不太同樣。只有在咱們往硬盤保存或者基於網絡傳輸時,才能肯定」你「究竟是一個漢字,仍是一個日本字,這就是unicode轉換成其餘編碼格式的過程了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#將bytes轉換爲str
name_b
=
b
'tom'
name_s1
=
name_b.decode(
'utf-8'
)
name_s2
=
str
(name_b,encoding
=
'utf-8'
)
print
(name_b,
type
(name_b))
#b'tom' <class 'bytes'>
print
(name_s1,
type
(name_s1))
#tom <class 'str'>
print
(name_s2,
type
(name_s2))
#tom <class 'str'>
#將str轉換爲bytes
gender
=
'male'
gender_b1
=
gender.encode(
'utf-8'
)
gender_b2
=
bytes(gender,encoding
=
'utf-8'
)
print
(gender,
type
(gender))
#male <class 'str'>
print
(gender_b1,
type
(gender_b1))
#b'male' <class 'bytes'>
print
(gender_b2,
type
(gender_b2))
#b'male' <class 'bytes'>
|