您好,登錄后才能下訂單哦!
前言
昨天團隊的學妹來問關于POP3協議的問題,所以今天稍稍研究了下POP3協議的格式和Python里面的poplib。而POP服務器往回傳的數據里有一部分需要用到Base64進行解碼,所以就順便看了下Python里面的base64模塊。
本篇先講一下base64模塊,該模塊提供了關于Base16,Base32,Base64,Base85和Ascii85的編碼和解碼相關的函數。有關poplib模塊的內容,會在后面發上來。嗯,又挖了一個坑,這輩子挖的坑填不完了...
以下內容摘自http://bbs.chinaunix.net/thread-1150250-1-1.html,詳細說明了為什么回傳的數據會先經過Base64編碼:
由於歷史原因,Internet上有些郵件系統只支援7Bit的字元傳輸,而漢字的內碼是8Bit的,當在電子郵件中發送中文時,如果經過這些只支援7Bit字元的郵件系統,便會將漢字內碼的第八位元的1全部變成0。
以”中文”兩字為例,HEX為A4A4A4E5,當最高位元被清掉時就會變成24242465,也就是”$$$e”。telnet也存在這樣子的問題。
除了中文郵件外,使用電子郵件傳送圖片、程式、壓縮文件等也會發生這個問題。所以在電子郵件中一般採用各種郵件編碼方式來解決這個問題,將8Bit按照一定的規則進行編碼,便可以完好地通過只支持7Bit字元的郵件系統。
常見的郵件編碼有UU與MIME,而MIME(Multipurpose Internet Mail Extentions)一般翻譯成「多媒體傳送模式」,顧名思義,它標榜的就是可以傳送多媒體型式的檔案,可以在一封mail中附加各種型式檔案一起送出。
MIME定義兩種編碼方法:Base64與QP(Quote-Printable),兩者使用時機不同,QP的規則是對於資料中的7bits無須重複encode,僅8bits資料轉成7bits。QP編碼適用於非US-ASCII的文字內容,例如我們的中文檔案,而Base64的編碼規則,是將整個檔案重新編碼,編成7bits,它是用於傳送binary檔案時使用。由於編碼的方式不同,會影響編碼之後的檔案大小。有些較懶惰的軟體便都一律採用Base64編碼了。
Base64
base64模塊提供了6個函數用于Base64的編碼和解碼,可以將他們分為三組。
base64.b64encode(s, altchars=None)
base64.b64decode(s, altchars=None, validate=False)
參數s代表需要編碼/解碼的數據。其中b64encode的參數s的類型必須是字節包(bytes)。b64decode的參數s可以是字節包(bytes),也可以是字符串(str)。
由于Base64編碼后的數據中可能會含有'+'或者'/'兩個符號,如果編碼后的數據用于url或者文件系統的路徑中,就可能會導致Bug。所以base64模塊提供了將編碼后的數據中'+'和'/'進行替換的方法。
參數altchars必須是長度為2的字節包,這兩個符號會用于替換編碼后數據中的'+'和'/'。這個參數默認是None。
參數validate默認為False。如果它為True時,base64模塊在進行解碼前會先檢查s中是否有非base64字母表中的字符,如果有的話則拋出錯誤binascii.Error: Non-base64 digit found。
如果數據的長度不正確則會拋出錯誤binascii.Error: Incorrect padding。
>>> import base64 >>> x = base64.b64encode(b'test') >>> x b'dGVzdA==' >>> base64.b64decode(x) b'test'
base64.standard_b64encode(s)
base64.standard_b64decode(s)
這組函數會直接將參數s傳到上一組函數中。
base64.urlsafe_b64encode(s)
base64.urlsafe_b64decode(s)
這組函數同樣基于第一組函數,但進行編碼后會將輸出數據中的'+'和'/'替換為'-‘和'_'。解碼前則將數據中的'-‘和'_'替換為'+'和'/'。
另,Base64編碼還會產生一個符號'=',這個符號用于將數據長度填充到4的倍數。
Base32
base64.b32encode(s)
base64.b32decode(s, casefold=False, map01=None)
參數s與Base64一致。
Base32編碼后的字符范圍為[2-7A-Z],是不支持小寫字母的。不過當參數casefold為True時,Base32解碼時可以接受小寫字母的輸入。但是為了安全考慮,這個參數默認為False。
Base32的解碼同時還允許將數字0替換為大寫字母O,把數字1替換為大寫字母I或者L。參數map01可以指定將數字1替換為哪個字符(源碼中并沒有限定必須是字母I或者L其中之一),當這個參數非None時,數字0總是會被替換為字母O。同樣為了安全考慮,這個參數默認為None。
Base16
base64.b16encode(s)
base64.b16decode(s, casefold=False)
Base16編碼后的字符范圍為[0-9A-F]。
參數s和casefold的作用與Base32一致。
Base85
base64.b85encode(b, pad=False)
base64.b85decode(b)
參數b為用于編碼/解碼的數據,類型要求跟Base64的參數s一致。
參數pad為True時,在編碼前會用b'\0'將數據填充到長度為4的倍數。不過在解碼的時候不會移除這些填充數據。
這組函數是在Python3.4之后新增的。
Ascii85
base64.a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False)
參數b為用于編碼的數據,類型必須為bytes。
參數foldspaces為True時會用b'y'來表示4個連續的空格。
參數wrapcol為一個整數,當wrapcol非0時,這個整數控制編碼后的輸出每多少個字符添加一個換行符b'\n'。
參數pad為True時,數據在編碼前會用b'\0'填充到長度為4的倍數。解碼的時候不會移除這些填充數據。
參數adobe指定了數據是否采用Adobe的格式。Adobe Ascii85的編碼數據由<\~和\~>包圍起來,如果這個參數為True,返回的數據會加上這對符號。
base64.a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v')
參數b為用于編碼的數據,類型可以為bytes或者str。
參數foldspaces為True時會用b'y'來表示4個連續的空格。
參數adobe指定了數據是否采用Adobe的格式。Adobe Ascii85的編碼數據由<\~和\~>包圍起來,如果這個參數為True,解碼前base64會先去掉這對符號。
參數ignorechars指定了解碼時需要忽略掉的字符。默認包含了ASCII中所有的空白符。
這組函數是在Python3.4之后新增的。
base64模塊的官方文檔中提到:Base85和Ascii85使用5個字符編碼4個字節,而Base64使用6個字符編碼4個字節(實際上是4個字符編碼3個字節),當空間不充裕時前兩者會比Base64更高效。
舊API
base64仍然保留了一部分舊的API,用于一些特殊用途。
base64.encode(input, output)
base64.decode(input, output)
這組函數使用二進制文件作為數據源,并將編碼/解碼后的數據寫入二進制文件。
base64.encodebytes(s)
base64.decodebytes(s)
encodebytes和b64encode在內部都是調用的binascii模塊的b2a_base64,只不過encodebytes調用b2a_base64時newline參數使用默認值True。也就是說,encodebytes在輸出數據的時候,每76個字節會添加一個換行符b'\n'。
decodebytes和默認參數下的b64decode基本一致。只有參數類型的檢查不一樣,decodebytes只支持bytes類型的數據。
base64.encodestring(s)
base64.decodestring(s)
這組函數在Python3.1之后就廢棄了,目前會直接調用上一組函數。
總結
base64模塊提供了對二進制數據進行編碼的接口,其中包括了標準的Base64,Base32,Base16和事實標準Ascii85和Base85。通過學習這個模塊,順便學習了一下二進制數據編碼的各種細節,感受頗深。有時候我們自以為了解計算機,了解互聯網,其實每個人看到的都只是滄海一粟,不值一提。這個領域對于我來說還有很多未知,是等待探索的,而我也不會停止探索的腳步。
以上就是本文關于Python使用base64模塊進行二進制數據編碼詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。