Base系列編碼淺析【base16 base32 base64 base85 base36 base 58 base91 base 92 base62】


Base系列編碼淺析

 
 
Base編碼有很多種,常用的有:
            base16   base32   base64   base85  base36  base 58  base91  base 92   base62
 

 

Base16

  •   使用16個ASCII可打印字符(數字0-9和字母A-F),對任意字節數據進行編碼。
  •      先獲取輸入字符串每個字節的二進制值(不足8比特在高位補0),然后將其串聯進來,再按照4比特一組進行切分,將每組二進制數分別轉換成十進制。
  •   Base16編碼后的數據量是原數據的兩倍:1000比特數據需要250個字符(即 250*8=2000 比特)。
 
                                    
 
:可以看到8比特數據按照4比特切分剛好是兩組,所以Base16不可能用到填充符號“=”。
  換句話說:Base16使用兩個ASCII字符去編碼原數據中的一個字節數據。
  Base16編碼是一個標准的十六進制字符串(注意是字符串而不是數值),更易被人類和計算機使用,因為它並不包含任何控制字符,以及Base64和Base32中的“=”符號。
 
 

 
 

Base32

 
  •    Base32編碼是使用32個可打印字符(字母A-Z和數字2-7)對任意字節數據進行編碼的方案,編碼后的字符串不用區分大小寫並排除了容易混淆的字符,可以方便地由人類使用並由計算機處理。
  •    Base32主要用於編碼二進制數據,但是Base32也能夠編碼諸如ASCII之類的二進制文本。
  •    Base32將任意字符串按照字節進行切分,並將每個字節對應的二進制值(不足8比特高位補0)串聯起來,按照5比特一組進行切分,並將每組二進制值轉換成十進制來對應32個可打印字符中的一個。
 
 
 
 
 
  由於數據的二進制傳輸是按照8比特一組進行(即一個字節),因此Base32按5比特切分的二進制數據必須是40比特的倍數(5和8的最小公倍數)。
 
  例如輸入單字節字符“%”,它對應的二進制值是“100101”,前面補兩個0變成“00100101”(二進制值不足8比特的都要在高位加0直到8比特),從左側開始按照5比特切分成兩組:“00100”和“101”,后一組不足5比特,則在末尾填充0直到5比特,變成“00100”和“10100”,這兩組二進制數分別轉換成十進制數,通過上述表格即可找到其對應的可打印字符“E”和“U”,但是這里只用到兩組共10比特,還差30比特達到40比特,按照5比特一組還需6組,則在末尾填充6個“=”。填充“=”符號的作用是方便一些程序的標准化運行,大多數情況下不添加也無關緊要,而且,在URL中使用時必須去掉“=”符號。
 

 

Base64

  •     Base64是一種基於64個可打印字符來表示二進制數據的表示方法。由於,所以每6個比特為一個單元,對應某個可打印字符。3個字節有24個比特,對應於4個Base64單元,即3個字節可由4個可打印字符來表示。
  •    在Base64中的可打印字符包括字母A-Z、a-z、數字0-9,這樣共有62個字符,此外兩個可打印符號在不同的系統中而不同。一些如uuencode的其他編碼方法。
  •    它可用來作為電子郵件的傳輸編碼。
  •     Base64常用於在通常處理文本數據的場合,表示、傳輸、存儲一些二進制數據,包括MIME的電子郵件及XML的一些復雜數據。
 
 
 
   注:BinHex的版本使用不同的64字符集來代表6個二進制數字,但是不被稱為Base64。
 
 
 
  如果要編碼的字節數不能被3整除,最后會多出1個或2個字節,那么可以使用下面的方法進行處理:
 
    (1)先使用0字節值在末尾補足,使其能夠被3整除,然后再進行Base64的編碼。
       (2)在編碼后的Base64文本后加上一個或兩個=號,代表補足的字節數。
 
  也就是說:
    當最后剩余兩個八位(待補足)字節(2個byte)時,最后一個6位的Base64字節塊有四位是0值,最后附加上兩個等號;
    如果最后剩余一個八位(待補足)字節(1個byte)時,最后一個6位的base字節塊有兩位是0值,最后附加一個等號。 
 
參考下表:
 
 
 
 

 
 
 

Base85

  •         base85 也稱為Ascii85,是Paul E. Rutter為btoa實用程序開發的一種二進制文本編碼形式。通過使用五個ASCII字符來表示四個字節的二進制數據(使編碼量1 / 4比原來大,假設每ASCII字符8個比特),它比更有效UUENCODE或Base64的,它使用四個字符來表示三個字節的數據(1 / 3的增加,假設每ASCII字符8個比特)。
  •         用途是Adobe的PostScript和Portable Document Format文件格式,以及Git使用的二進制文件的補丁編碼。
  •         與Base64一樣,Base85編碼的目標是對二進制數據可打印的ASCII字符進行編碼。但是它使用了更大的字符集,因此效率更高一些。具體來說,它可以用5個字符編碼4個字節(32位)。
 
摘自wiki介紹的一個例子:
 
 
 

 
 
 

Base36

 
 
Base36是一個二進制到文本編碼表示方案的二進制數據以ASCII通過將其轉化為一個字符串格式基數 -36表示。選擇36十分方便,因為可以使用阿拉伯數字 0–9和拉丁字母 A–Z [1](ISO基本拉丁字母)表示數字。
每個base36位需要少於6位的信息來表示。
 
摘自wiki的一個例子:
 
有符號的32位和64位整數分別最多只能容納6個或13個base-36位數字(許多base-36位數字可能會使32位和64位整數溢出)。
 
例如,在base-36中,“ 922337203685477575807 ” 的64位帶符號整數最大值為“ 1Y2P0IJ32E8E7 ”。
類似地,在base-36中,“ 2147483647 ” 的32位帶符號整數最大值為“ ZIK0ZJ ”。
 
(這里沒看太懂是怎么轉換的,請大佬指教~)
 
用於從BASE10編碼BASE36的Python代碼
 
def base36encode(integer): 
    chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 
    
     sign = '-' if integer < 0 else '' 
     integer = abs(integer) 
     result = '' 
 
     while integer > 0: 
         integer, remainder = divmod(integer, 36) 
         result = chars[remainder]+result
 
      return sign+result

 

 
 
 

 

Base58

 
  •         Base58是用於Bitcoin中使用的一種獨特的編碼方式,主要用於產生Bitcoin的錢包地址。
  •         相比Base64,Base58不使用數字"0",字母大寫"O",字母大寫"I",和字母小寫"l",以及"+"和"/"符號
  
  設計Base58主要的目的是:
  1. 避免混淆。在某些字體下,數字0和字母大寫O,以及字母大寫I和字母小寫l會非常相似。
  2. 不使用"+"和"/"的原因是非字母或數字的字符串作為帳號較難被接受。
  3. 沒有標點符號,通常不會被從中間分行。
  4. 大部分的軟件支持雙擊選擇整個字符串。
 
 
 
 

 
 
 

Base91

 
  顧名思義,basE91需要91個字符來表示ASCII編碼的二進制數據。 從94個可打印ASCII字符(0x21-0x7E)中,以下三個字符被省略以構建basE91字母:
 
    -(破折號,0x2D)
    \(反斜杠,0x5C)
    '(撇號,0x27)
  •     basE91是將二進制數據編碼為ASCII字符的高級方法。 
  •     它類似於UUencode或base64,但效率更高。 basE91產生的開銷取決於輸入數據。 它的數量最多為23%(而base64為33%),范圍可以降低到14%,通常發生在0字節塊上。 
  •     這使得basE91對於通過二進制不安全連接(例如電子郵件或終端線)傳輸較大的文件非常有用。
 
 
 
轉換表由其余字符組成,如下所示。
 
 

 
 

Base92

 
 
  有關Base92的資料實在是很少,但是筆者找到了這一篇博客:
 
    https://thenoviceoof.com/blog/projects/base92/
 
以下介紹均摘自這篇博客

 

  “  如果您對將二進制信息從一個地方轉移到另一地方一無所知,那么就知道將數據從一個地方轉移到另一地方 可能很危險。就是說,這對您的數據有害:也許您需要在僅用於ASCII文本的通道上傳輸Blob ,並且所有'\n'以C樣式字符串表示的字節都會突然有一個同級符號'\r'。或者,您的傳輸層實際上真的真的是以null終止的字符串,並且您恰好在字節邊界上連續有8個連續的0位,即使它位於blob中一個32位整數的中間,並且你結束了只有一半您的數據。
 
  解決此問題的一種方法是使用base64,它使用所有數字和大寫/小寫字母字符對數據進行編碼(再加上兩個,但現在我們將忽略它們)。現在,您在傳輸層上嘗試解釋您的字節時沒有任何問題,因為每個人都可以很好地處理字母數字字符,如果沒有,您可能不想使用它們。
當然,使用base64了一段時間后,您可能會注意到,雖然您不會因為一位反復無常的上帝以為他在提供幫助,卻沒有按照自己的意願對數據進行更改,但您卻通過使用放棄了效率base64。對於二進制blob中的每3個字節,如果需要傳輸字母數字字符,則有4個字節,因此您要以33%的容量稅來支付數據保護費用:如果暴徒可以在保護球拍中掠走33%,相信他們會的。
  看一下base64,您可能會注意到,除了可以使用的64個字符外,還有更多可顯示的ASCII字符,base64可以在編碼中使用這些字符以提高傳輸密度。這樣就base85誕生了,使用了……您猜對了,有85個字符!這次,將4字節的二進制數據編碼為5個ASCII字符,這將導致20%的傳輸大小開銷。但你能做什么呢?好像沒有更多可顯示的ASCII了……哦,等等。
 
  所以似乎沒有人試圖超越明顯的下一步base85,所以我決定嘗試自己做base92。
 
  在鍵入編碼的字符串時,`和“與普通引號'太相似,以使其舒適。希望在區分l / 1和0 / O時使用的字體好。但是,我們將〜用作特殊符號(空字符串)。有94個可打印的ascii字符,因此我們最終得到91個字符,或每個字符6.5位。一旦包含〜,則將有92個字符:因此,為base92。(老實說,base91的名字太丑陋了,無法處理)
  一旦每個字符有6.5位,則可以一次使用13位,並使用類似於base85的除法和取模方案,用它們產生兩個輸出字符。這可能意味着,與base92編碼相比,它更能抵抗損壞,因為任何損壞都更加局限(一位更改僅影響2-3個字節,而不影響4個字節)。
 
 
注意:在某些需要某些輸出的情況下,可能需要將〜用作空字符串分號:但是,傳遞空字符串進行解碼不會導致它變成barf,因此不要求使用〜。
旁注:以前base92產生的輸出的長度與輸入的長度非單調增長。這已不再是這種情況。
另一個旁注:base64和base85更加優雅,將一個較小的字節整數干凈地映射到另一個較小的字節整數。base92將13個字節映射為16個字符,從大小的角度來看,這比base85的4至5個字符更好,但是相當不雅觀。我們還遵循使用高除數乘積作為第一個字節的base85約定。”
 
 
 
以上是筆者用谷歌翻譯直接搬運的,如有描述不懂的小伙伴,請參照原文鏈接進行參考~
 

 
 

Base62

 
 
  • Base62編碼將數字轉換為ASCII字符串(0-9,az和AZ),反之亦然,這通常會導致字符串較短。
               26個小寫字母+26個大寫字母+10個數字=62
 
 
(1)62進制與10進制的互相轉化
 
  •   62進制轉10進制與2進制轉10進制相似。
        2進制轉10進制過程為: 從右到左用二進制的每個數去乘以2的相應次方,次方要從0開始。
        62進制轉10進制也類似,從右往左每個數*62的N次方,N從0開始。
 
 
 
  那么,10進制轉62進制也與10進制轉2進制類似。  即:不斷除以62取余數,然后倒序。
 
 
(2)關於短Url的轉換
 
    主要思路,維護一個全局自增的id,每來一個長url,將其與一個自增id綁定,然后利用base62將該自增id轉換為base62字符串,即完成轉換。

 
 
 
 
 以上就是對Base系列編碼的淺析,部分知識是筆者從wiki上搬運過來的,也參考了很多博客文章和資料。如有錯誤及不足之處,請大佬們多提建議~
 
 
 
 
 
 
參考資料:
 
 
https://en.wikipedia.org/wiki
 
https://blog.csdn.net/n0nameforn0w/article/details/87124053
 
https://thenoviceoof.com/blog/projects/base92/
 
https://segmentfault.com/a/1190000010516708
 
 
 
 
 
 


免責聲明!

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



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