高中信息技術(Python)重難點2:字符編碼


本文章原文地址:https://www.cnblogs.com/BobHuang/p/15497994.html,原文體驗更佳
字符編碼在近兩年高考中分別在20年1月、21年1月和21年6月選擇題第4題出現,往往和重難點1:數制一起出現。較為重要。

一、編碼概述

編碼(Encoding)是信息按照某種規則或格式,從一種形式轉換為另一種形式的過程。解碼是編碼的逆過程。
計算機對信息進行存儲、加工、傳遞等處理,實際上是對信息的載體——數據進行處理。數據的表現形式可以是文本、圖形、圖像、聲音、視頻等,但不管是哪種形式的數據,最終存儲在計算機中的都是經過一定規則編碼后的二進制數字。

二、ASCII碼

ASCII(American Standard Code for Information Interchange,美國信息交換標准代碼)是一套基於拉丁字母的計算機編碼系統,主要用於顯示現代英語和其他西歐語言。它由電報碼發展而來,是現今最通用的單字節編碼系統。基本的ASCⅢ碼共有128個,用1個字節中的低7位編碼。二進制范圍為000000111111,即十六進制的00H~7FH。基本的ASCⅢ碼由33個控制字符、10個阿拉伯數字、26個英文大寫字母、26個英文小寫字母與些標點符號、運算符號組成。
ASCII碼值及對應的字符,建議收藏。
常用的有空格為32(20H),'0'為48(30H),'A'為65(41H),'a'為97(61H),'A'與'a'相差32(20H)。
給定一個字符,想要獲取其ASCII碼怎么做呢?可以使用Python內置的ord函數,字符型->整型可以用ord函數。對應題目為TZOJ5885: ASCII表

ord()函數

ord函數以一個字符(長度為1的字符串)作為參數,返回對應的 ASCII 數值,或者 Unicode 數值

TZOJ5885參考代碼

a=input()
print(ord(a))

若知道ASCII值,能轉換為字符嗎?可以使用Python內置的chr函數,整型->字符型可以用chr函數。對應題目為TZOJ5889: 打印字符

chr函數

chr() 用一個范圍在256內的整數作參數,返回一個對應的字符。

5889參考代碼

# 注意輸入的類型為int
a=int(input())
print(chr(a))

你可以嘗試下以下題目

TZOJ7178 小z與ASCII加密、TZOJ6446 小z與ASCII解密、TZOJ1492 C語言實驗題――大小寫轉換、TZOJ1489 C語言實驗題――字符編碼

要想顯示出字母,系統中還必須裝有相應的字庫(Font,又稱字型)。字庫中存儲了每個字符的形狀信息,如字母'A'的點陣字符如下所示

TZOJ6972: 點陣字符 可以嘗試下。
字庫分為點陣字符和矢量字符,矢量字符記錄的是字符的筆畫,具有存儲空間小、美觀的優點。

三、漢字編碼

計算機中的漢字是采用二進制進行編碼的。漢字編碼分為外碼、交換碼、機內碼和字形碼。
外碼:又稱輸入碼,是用來將漢字輸入到計算機中的一組鍵盤符號。常用的輸入碼有拼音碼、五筆字形碼等。
交換碼:又稱國標碼,是和別的計算機交換信息時使用的編碼。
機內碼:根據國標碼的規定,每一個漢字都有確定的二進制代碼,在計算機內部漢字代碼都用機內碼,在磁盤上記錄存儲漢字代碼也使用機內碼。它們的集合就叫字符集。
字形碼:又稱輸出碼、漢字字模,把二進制的漢字編碼還原為可視的圖形,將其顯示出來,它們的集合又叫字庫。

四、GB2312編碼

為了解決計算機的漢字顯示問題,國家標准化管理委員會發布了GB/T 2312-1980,簡稱GB 2312。在GB 2312字符集中,1個漢字在計算機中用2個字節表示。如下圖中的"中國China"這幾個字符,其中"中國"兩個漢字的內碼為D6 DO B9 FA,而英文字符"China"是ASCII字符,其中每個字母都用1個字節編碼表示。

圖片中使用的軟件是UltraEdit,使用Python可以直接將其內碼依次顯示。

a='中國China'
# 使用gb2312進行編碼
a=a.encode('gb2312')
# 依次輸出每個字節的值
for i in a:
    # 使用16進制輸出
    print("%02X" % i,end=" ")

GB 2312標准共收錄6763個漢字,其中一級漢字3755個,二級漢字3008個。GB 2312的出現,基本滿足了漢字的計算機處理需要,它所收錄的漢字已經覆蓋中國大陸99.75%的使用頻率。
使用GB 2312時采用EUC-CN(Extended Unix Code)儲存方法,以便兼容於ASCII。ASCII取值范圍00H~7FH,兩個連續的大於7FH的字符連接在一起就表示漢字
同時,GB 2312收錄了包括一般符號、數字、希臘字母、日文假名、俄文字母等在內的682個字符。ASCII碼內本來就有的標點、數字、字符等在GB 2312中依舊被編碼了,我們把他們稱為全角字符,ASCII內就叫做半角字符,他們在計算機顯示是不一樣的,全角字符往往要寬一點。

想要更進一步了解GB2312的區位碼可以嘗試下 TZOJ7334: GB2312區位碼

五、* GBK編碼

GB 2312中雖然已有6763個漢字,但是像有些生僻字"珽"以及繁體字"甦"等均無法顯示。如果系統所用的是GB 2312,遇到這些字往往不能顯示。還有1萬多個漢字和需要編碼,於是人們就想到了擴充,發布了《漢字內碼擴展規范》,簡稱GBK(國標擴展)。GBK 向下與 GB 2312 編碼兼容,向上支持 ISO 10646.1國際標准(國際標准組織ISO公布的通用字符集UCS),,它與 Unicode 組織的 Unicode 編碼完全兼容。第一個字節還滿足大於7FH,第二個字節范圍為40H到FEH。
使用Python查看其gbk內碼時把上文代碼中的encode設為gbk即可。

a='甦'
# 使用gbk進行編碼
a=a.encode('gbk')
# 依次輸出每個字節的值
for i in a:
    # 使用16進制輸出
    print("%02X" % i,end=" ")

六、* GB18030編碼

為了解決中文、國內少數民族文字、日文以及朝鮮語等的編碼,國家標准化管理委員會又發布了GB 18030,現行標准為GB18030-2005,GB/T 2312-1980自2017年3月23日起轉化為推薦性標准,不再強制執行。
GB 18030包含三種長度的編碼:單字節的ASCII、雙字節的GBK(略帶擴展)、以及用於填補所有Unicode碼位的四字節UTF區塊。

七、Unicode字符集

隨着互聯網的快速發展,各國之間的交流由於語言不同成為障礙,能否設計出讓650種語言都兼容的字符集呢,Unicode協會將所有這些語言字符統一為一套字符集解決了這個問題。
Unicode字符集又稱萬國碼,往往用U+一個16進制數字表示,目前已經編碼到10FFFFH,貨幣元¥為U+00A5,實心電話☎為U+260E,漢字煩為U+70E6,表情喜極而泣😂為U+1F602。
具體每個字符編碼值 可以到https://unicode-table.com/cn查詢

使用Python代碼可以查到每個字符的Unicode符號值。

a='中國¥☎😂'
# 使用unicode-escape編碼集
a=a.encode('unicode-escape')
print(a)

八、* UTF-8編碼

Unicode字符集只規定了字符與碼表的一一對應關系,卻沒有規定該如何實現,因此這個字符集有多種實現方式(UTF-8,UTF-18,UTF-32),常見的實現方式是UTF-8。
UTF-8采用變長的編碼方式實現,其節省空間,兼容ASCII標准的優點, 在互聯網上使用最廣的一種Unicode的實現方式。

UTF-8 的編碼規則很簡單,只有二條:
1.對於單字節的符號,字節的第一位設為0,后面7位為這個符號的 Unicode 碼。因此對於英語字母,UTF-8 編碼和 ASCII 碼是相同的。
2.對於n字節的符號(n > 1),第一個字節的前n位都設為1,第n + 1位設為0,后面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的 Unicode 碼。

Python代碼依舊可以查出其utf-8編碼值

a='煩'
# 使用utf-8進行編碼
a=a.encode('utf-8')
# 依次輸出每個字節的值
for i in a:
    # 使用16進制輸出
    print("%02X" % i,end=" ")

漢字的長度從2字節變為3字節了,所以實際在網絡傳輸中還是會使用其Unicode值進行傳輸的,而且我們也不知道用戶使用什么編碼,比如json中漢字為\u+四位十六進制數。

規定UTF-8編碼規則能不能寫出其轉換程序呢?TZOJ7335: UTF-8編碼等你來嘗試。

九、Base64編碼

Base64編碼是計算機中常見的一種編碼方式,規則是把3個字節(24位)的數據按6位1組分成4組(24÷6=4),然后將每組數據分別轉換為十進制,根據下圖將這些十進制數所對應的字符連接,即為Base64編碼。

以編碼字符“Web”為例,如下圖所示,字符“Web”對應的ASCI編碼分別是87,101,98,分別轉換為8位二進制數,按6位二進制數分組后再轉換成十進制,査找它們的對應字符,得到“Web”的Base64編碼為“V2Vi”。

TZOJ7212: Base64編碼簡單版 給你一個長度是3的倍數的字符串,請你找出其Base64編碼的值。
這個過程實際上就是進制轉換的過程,可以寫出如下代碼
7212參考代碼1

# base64表
base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
a=input()
# 3位一處理
for i in range(0,len(a),3):
    # 連續的3位按照256進制轉換為數字
    x=ord(a[i])*256*256+ord(a[i+1])*256+ord(a[i+2])
    # 按照64進制轉換回去
    print(base64_table[x//64//64//64],
    base64_table[x//64//64%64],
    base64_table[x//64%64],
    base64_table[x%64],
    end="",sep="")

也可以使用Python內置的base64模塊

7212參考代碼2
from base64 import b64encode
data = input()
print(b64encode(data.encode()).decode())

如果原始的字節數不是3的倍數,比如4字節(剩余1字節)或者5字節(剩余2字節),則需要再末尾處理,一共可以分為2種情況。
1.如果剩余1字節,需要補2字節(16bit)才是3的倍數。也就是要則補16個0,加上前面剩余的1字節(8bit),一共是24個bit,其中24個bit的前12bit(2*6)構成兩個base64字符,剩下的12bit(2*6)全部是0,用兩個等號 == 表示。
2.如果剩余2字節,需要補1字節(8bit)才是3的倍數。也就是要則補8個0,加上前面剩余的2字節(16bit),一共是24個bit,其中24個bit的前18bit(3*6)構成三個base64字符,剩下的6bit(1*6)全部是0,用一個等號 = 表示。

了解了以上規則,TZOJ 7214: Base64編碼 等你來AC。

編碼會了,解碼要不要嘗試一下呢?TZOJ7213 Base64編碼解碼簡單版、TZOJ7215 Base64編碼解碼

十、小結

計算機表示數字數字非常方便,但是遇到字符卻不太好表示,發明計算機的美國人使用ASCII碼表示英文以及控制字符等。等到中國人要用時,並沒有我們的漢字,國家標准化管理委員會發布了GB 2312,但是其囊括漢字有限,微軟推出了GBK。國家標准化管理委員會又發布了GB 18030,完全兼容GBK。后來發布的均兼容之前的,所以只要是上述出現的編碼,使用GB 18030就不會出現亂碼了。

每個國家都可以自己制定一套編碼自己使用,為了世界不同語言的可以交流,我們發明了Unicode字符集。Unicode為了包含所有文字,使用更多位的字節的表示。對於有些文字使用多字節是比較浪費的,比如數字1,在ASCII碼中使用一個字節就能夠表示,在Unicode中有可能就是多字節表示,非常浪費存儲。UTF-8是Unicode的一種實現方式。實際情況使用變字節的來表示文字。使用1~4個字節表示一個字符,根據不同的字符而變化字節長度,當字符在ASCII 碼的范圍時,就用一個字節表示,而一個中文字符占3個字節。這個和我們中文GB的編碼是不同的,所以會出現亂碼。不過UTF-8編碼也兼容ASCII碼,所以里面的英文是可以正常顯示的。

參考:

  1. GB2312、GBK、GB18030 這幾種字符集的主要區別是什么?https://www.zhihu.com/question/19677619
  2. 標准號:GB/T 2312-1980 中文標准名稱:信息交換用漢字編碼字符集 基本集 http://www.gb688.cn/bzgk/gb/newGbInfo?hcno=5664A728BD9D523DE3B99BC37AC7A2CC
  3. 標准號:GB 18030-2005 中文標准名稱:信息技術 中文編碼字符集 http://www.gb688.cn/bzgk/gb/newGbInfo?hcno=C344D8D120B341A8DD328954A9B27A99


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM