日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python--字符/文本编码解码笔记

發(fā)布時(shí)間:2023/12/3 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python--字符/文本编码解码笔记 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

字符/文本編碼解碼筆記

  • 1.字符問題
    • 編碼和解碼
  • 2.字節(jié)概要
  • 3.基本的編解碼器
    • 編碼類型史
      • 字符編碼
      • ASCII碼
      • GB2312以及其他編碼
      • UNICODE標(biāo)準(zhǔn)編碼
      • UTF-8編碼
  • 4.了解編解碼問題
    • 處理UnicodeEncoderError
      • 解決方法:
    • 處理UnicodeDecodeError
      • 解決方法
  • 5.修改源代碼編碼
  • 6.查看文件編碼方式
    • 終端查看文件編碼方式
    • 代碼內(nèi)查看文件編碼方式
  • 7.處理文本文件
    • 查看open函數(shù)默認(rèn)編碼方式

1.字符問題

“字符串”是個(gè)相當(dāng)簡(jiǎn)單的概念:一個(gè)字符串是一個(gè)字符序列。
在 2015 年,“字符”的最佳定義是 Unicode 字符。因此,從 Python 3 的 str 對(duì)象中獲取的元素是 Unicode 字符。但是Python 3 默認(rèn)使用 UTF-8 編碼源碼。注意區(qū)分。
Unicode 標(biāo)準(zhǔn)把字符的標(biāo)識(shí)和具體的字節(jié)表述進(jìn)行了如下的明確區(qū)分。

  • 字符的標(biāo)識(shí),即碼位,是 0~1 114 111 的數(shù)字(十進(jìn)制),在 Unicode 標(biāo)準(zhǔn)中以 4~6 個(gè)十六進(jìn)制數(shù)字表示,而且加前綴“U+”。例如,字母 A 的碼位是 U+0041。
  • 字符的具體表述取決于所用的編碼,也就是除了Unicode以外其他編碼的表示。編碼是在碼位和字節(jié)序列之間轉(zhuǎn)換時(shí)使用的算法。比如在 UTF-8 編碼中,A(U+0041)的碼位編碼成單個(gè)字節(jié) \x41。一個(gè)字符串則編碼為由多個(gè)字節(jié)組成的字節(jié)序列。后面會(huì)多處提到字節(jié)序列,把它當(dāng)成用其他編碼器對(duì)Unicode字符編碼的結(jié)果就可以了。

編碼和解碼

編碼是把碼位轉(zhuǎn)換成字節(jié)序列的過程。通俗的講就是將Unicode編碼的字符轉(zhuǎn)化為其他編碼的字符。
解碼是把字節(jié)序列轉(zhuǎn)換成碼位的過程。通俗的講就是將其他編碼的字符轉(zhuǎn)化為Unicode編碼的字符。

s='sabér' print(s) print(len(s)) #1 b=s.encode('utf-8') #2 print(b) #3 print(len(b)) #4 x=b.decode('utf-8')#5 print(x)

輸出:

sabér 5 b'sab\xc3\xa9r' 6 sabér
  • 1.'sabér'字符串有5個(gè)Unicode字符。
  • 2.使用UTF-8把str對(duì)象編碼成bytes對(duì)象。
  • 3.bytes字面量以b開頭,表示字節(jié)序列。
  • 4.字節(jié)序列 b 有 5 個(gè)字節(jié)(在 UTF-8 中,“é”的碼位編碼成兩個(gè)字節(jié))。
  • 5.使用 UTF-8 把 bytes 對(duì)象(字節(jié)對(duì)象)解碼成str 對(duì)象。

由于Unicode編碼是標(biāo)準(zhǔn)編碼格式,也可以看做是沒有任何特定編碼格式的“無編碼”模式。所以,對(duì)于任何Unicode類型編碼的字符,打印時(shí)python會(huì)自動(dòng)根據(jù)環(huán)境編碼轉(zhuǎn)為特定編碼后再顯示,Python 3 為所有平臺(tái)設(shè)置的默認(rèn)編碼都是 UTF-8。

2.字節(jié)概要

Python 內(nèi)置了兩種基本的二進(jìn)制序列類型:不可變 bytes 類型和 可變 bytearray 類型。

3.基本的編解碼器

Python 自帶了超過 100 種編解碼器(codec, encoder/decoder),用于在文本和字節(jié)之間相 互轉(zhuǎn)換。每個(gè)編解碼器都有一個(gè)名稱,如 ‘utf_8’,而且經(jīng)常有幾個(gè)別名,如 ‘utf8’、‘utf-8’ 和 ‘U8’。

  • 上圖有12個(gè)字符,code point表示其碼位,還有7種編碼的字節(jié)表述(十六進(jìn)制)。
  • 星號(hào)表明,某些編碼(如 ASCII 和多字節(jié)的 GB2312)不能表示所有 Unicode 字符。然而,UTF 編碼的設(shè)計(jì)目的就是處理每一個(gè) Unicode 碼位。

編碼類型史

字符編碼

將人類語言轉(zhuǎn)化為計(jì)算機(jī)能夠理解的二進(jìn)制的數(shù)(0,1),我們用bit(位)來表示,通常轉(zhuǎn)化的時(shí)候是按byte(字節(jié))來處理,一個(gè)字節(jié)等于8bit。

ASCII碼

ASCII碼是人類計(jì)算機(jī)歷史上最早發(fā)明的字符集,ASCII碼是專門為表示英文、數(shù)字以及英文標(biāo)點(diǎn)符號(hào)而生。ASCII編碼使用一個(gè)字節(jié)編碼,一個(gè)字節(jié)有256種組合,足夠存儲(chǔ)這些字符。

GB2312以及其他編碼

由于中文漢字非常多,ASCII無法滿足漢字存儲(chǔ)的需求。
為了滿足國內(nèi)在計(jì)算機(jī)中使用漢字的需要,中國國家標(biāo)準(zhǔn)總局發(fā)布了一系列的漢字字符集國家標(biāo)準(zhǔn)編碼,統(tǒng)稱為GB碼,或國標(biāo)碼
其中最有影響的是于1980年發(fā)布的《信息交換用漢字編碼字符集 基本集》,標(biāo)準(zhǔn)號(hào)為GB 2312-1980,因其使用非常普遍,也常被通稱為國標(biāo)碼。GB2312編碼通行于我國內(nèi)地;新加坡等地也采用此編碼。幾乎所有的中文系統(tǒng)和國際化的軟件都支持GB 2312。
所以,大家可以理解為,GB系列的編碼是為了適應(yīng)復(fù)雜的中文編碼而對(duì)ASCII碼的一種擴(kuò)充。

UNICODE標(biāo)準(zhǔn)編碼

每個(gè)國家都會(huì)對(duì)ASCII碼擴(kuò)展出自己的一套編碼,就存在不同編碼之間的轉(zhuǎn)換和顯示問題。為了解決這個(gè)問題,需要一套統(tǒng)一的編碼格式,即Unicode。
Unicode又被稱為統(tǒng)一碼、萬國碼;它為每種語言中的每個(gè)字符設(shè)定了統(tǒng)一并且唯一的二進(jìn)制編碼,以滿足跨語言、跨平臺(tái)進(jìn)行文本轉(zhuǎn)換、處理的要求。
Unicode編碼通常由兩個(gè)字節(jié)組成,共表示256*256個(gè)字符,即所謂的UCS-2。某些偏僻字還會(huì)用到四個(gè)字節(jié),即所謂的UCS-4。
并且Unicode兼容ASCII,在Unicode中,原本ASCII中的127個(gè)字符只需在前面補(bǔ)一個(gè)全零的字節(jié)即可。

UTF-8編碼

UNICODE編碼有個(gè)缺點(diǎn),所有語言的字符都是固定長(zhǎng)度的存儲(chǔ),有些語言的字符只需占用少量的存儲(chǔ)空間,這就導(dǎo)致浪費(fèi)了大量的存儲(chǔ)空間。
為了解決這個(gè)問題,就出現(xiàn)了一些中間格式的字符集,他們被稱為通用轉(zhuǎn)換格式,即UTF(Unicode Transformation Format)。
我們最常用的UTF-8就是這些轉(zhuǎn)換格式中的一種。UTF-8編碼其實(shí)是一種可“變長(zhǎng)”的編碼格式,即把英文變長(zhǎng)為1個(gè)字節(jié),而漢字用3個(gè)字節(jié)表示,特別生僻的還會(huì)變成4-6字節(jié)。

該部分參考:一文搞懂Python字符編碼問題

4.了解編解碼問題

雖然有個(gè)一般性的 UnicodeError 異常,但是報(bào)告錯(cuò)誤時(shí)幾乎都會(huì)指明具體的異常:UnicodeEncodeError(把字符串轉(zhuǎn)換成二進(jìn)制序列時(shí))或 UnicodeDecodeError(把二進(jìn)制序列轉(zhuǎn)換成字符串時(shí))。如果源碼的編碼與預(yù)期不符, 加載 Python 模塊時(shí)還可能拋出 SyntaxError。

處理UnicodeEncoderError

多數(shù)非 UTF 編解碼器只能處理 Unicode 字符的一小部分子集。把文本(Unicode 字符)轉(zhuǎn)換成字節(jié)序列時(shí),如果目標(biāo)編碼中沒有定義某個(gè)字符,那就會(huì)拋出 UnicodeEncodeError 異常。

解決方法:

  • 1.在encode()函數(shù)中添加參數(shù)error,舉例如下:
city = 'S?o Paulo' x=city.encode('cp437', errors='ignore') print(x) y=city.encode('cp437', errors='replace') print(y) z=city.encode('cp437', errors='xmlcharrefreplace') print(z)

輸出:

b'So Paulo' b'S?o Paulo' b'São Paulo'

error=‘ignore’ 處理方式悄無聲息地跳過無法編碼的字符;
error='replace’把無法編碼的字符替換成 ‘?’;
error=‘xmlcharrefreplace’ 把無法編碼的字符替換成 XML實(shí)體。

以上解決是十分不妥的,損壞了數(shù)據(jù)。
編解碼器的錯(cuò)誤處理方式是可擴(kuò)展的。你可以為 errors 參數(shù)注冊(cè)額外的字符串,方法是把一個(gè)名稱和一個(gè)錯(cuò)誤處理函數(shù)傳給 codecs.register_error 函數(shù)。 參見 codecs.register_error 函數(shù)的官方文檔。

  • 2.換一種編碼器,盡量使用UTF-8編碼器。

處理UnicodeDecodeError

ASCII字符有127個(gè),但是一個(gè)字節(jié)表示的空間有256個(gè)。所以不是每一個(gè)字節(jié)都包含有效的 ASCII 字符。
同理,不是每一個(gè)字符序列都是有效的 UTF-8 或 UTF-16。
把二進(jìn)制序列(字節(jié)序列)轉(zhuǎn)換成文本(Unicode字符)時(shí),如果字節(jié)序列有無效的字節(jié)時(shí),遇到無法轉(zhuǎn)換的字節(jié)序列時(shí)會(huì)拋出 UnicodeDecodeError。
舉例如下:

octets = b'Montr\xe9al' oct=octets.decode('cp1252') print(oct) oct1=octets.decode('utf_8') print(oct1) oct2=octets.decode('utf_8', errors='replace') print(oct2)

輸出:

Montréal Traceback (most recent call last):File "c:\Users\13451\Desktop\python基本操作\1.py", line 18, in <module>oct1=octets.decode('utf_8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte 'Montral'
  • 這些字節(jié)序列是使用 latin1 編碼的“Montréal”;’\xe9’ 字節(jié)對(duì)應(yīng)“é”。
  • 可以使用 ‘cp1252’(Windows 1252)解碼,因?yàn)樗?latin1 的有效超集。
  • ‘utf_8’ 編解碼器檢測(cè)到 octets 不是有效的 UTF-8 字符串,拋出 UnicodeDecodeError。bug中position從零開始數(shù)。

解決方法

使用 ‘replace’ 錯(cuò)誤處理方式,\xe9 替換成了替換字符(碼位是 U+FFFD),這是官方指定的 REPLACEMENT CHARACTER(替換字符),表示未知字符。替換字符:形狀為黑色菱形,且中間填充了一個(gè)問號(hào)。

5.修改源代碼編碼

Python 3 默認(rèn)使用 UTF-8 編碼源碼且Python 3 為所有平臺(tái)設(shè)置的默認(rèn)編碼都是 UTF-8。
在源代碼第一行加# coding: cp1252即可用cp1252編碼,或者編輯器或IDE都有更改編碼的途徑。

6.查看文件編碼方式

終端查看文件編碼方式

安裝統(tǒng)一字符編碼偵測(cè)包 Chardet。
終端使用:

chardetect 1.py

輸出:

1.py: utf-8 with confidence 0.99

表示1.py有0.99的可能是utf-8編碼。

代碼內(nèi)查看文件編碼方式

使用chardet庫的detect函數(shù)

import chardet file1='data/test.txt' f=open(file1,'rb') f_encoding=chardet.detect(f.read()) print(f_encoding) f.close()

輸出:

{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

7.處理文本文件

使用open()函數(shù)打開文件,有兩種方式處理文件:文本模式二進(jìn)制模式
添加encoding參數(shù)可以設(shè)置編碼方式,這個(gè)編碼方式在編碼輸出文本的時(shí)候會(huì)用到,即下圖第三行。open()函數(shù)默認(rèn)采用文本模式。默認(rèn)編碼方式取決于平臺(tái),window10下為gbk,linux下為utf-8。當(dāng)處于二進(jìn)制模式時(shí)不能添加encoding參數(shù),因?yàn)楸旧砭褪嵌M(jìn)制了,不需要再編碼。

  • 如果調(diào)用read()函數(shù),open 函數(shù)會(huì)在讀取文件時(shí)做必要的解碼(自動(dòng)解碼成Unicode字符,即str)。對(duì)應(yīng)下圖解碼輸入的字節(jié)序列,得到str對(duì)象。
  • 如果調(diào)用write()函數(shù),以文本模式寫入文件時(shí)還會(huì)做必要的編碼。參數(shù)為str對(duì)象。對(duì)應(yīng)下圖第三行,生成字節(jié)序列(bytes)。

整個(gè)處理文本文件的過程如下圖:

查看open函數(shù)默認(rèn)編碼方式

file1='data/test.txt' fp=open(file1,'w') print(fp) fp.close()

win10下輸出:

<_io.TextIOWrapper name='data/test.txt' mode='w' encoding='cp936'>

cp936即 code page 936(代碼頁936)是以GBK(國標(biāo)擴(kuò)展字符集)為基礎(chǔ)的編碼。基本和GBK差不多。

關(guān)于編碼默認(rèn)值的最佳建議是:別依賴默認(rèn)值。如果遵從 Unicode 三明治的建議,而且始終在程序中顯式指定編碼,那將避免很多問題。

參考了流暢的python第四章。

總結(jié)

以上是生活随笔為你收集整理的python--字符/文本编码解码笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。