1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          實現 Base64 的編碼解碼

          來源:互聯網轉載 時間:2024-01-29 08:06:54

          1. 什么是 Base64 ?

          Base64 是一種基于 64 個可打印字符來表示二進制數據的表示方法。由A-Z(26),a-z(26),0-9(10),加+,/,=(3) 其實是 65 個字符(注:等號 = 用來作為后綴用途),如下所示

          let?_keyStr?=?'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='

          用途:Base64 常用于在處理文本數據的場合,表示、傳輸、存儲一些二進制數據,包括 MIME 的電子郵件及 XML 的一些復雜數據。在 MIME 格式的電子郵件中,base64 可以用來將二進制的字節序列數據編碼成 ASCII 字符序列構成的文本,可以防止因不可見字符在傳輸過程中被錯誤處理導致內容有誤。

          注:ASCII碼為 unicode碼范圍 0- 127 的字符, 128-255 為不可見字符

          2. Base64 原理

          Base64 除去補位符=共有64個字符(即26) 可表示二進制 000000111111之間的數字,共六個比特位。我們知道,一個字節有 8 個比特位,因此這兩者的最小公倍數為 24,即 3 字節的數據可以由 4 個 Base64 字符表示:

          實例演示

          我們以 hi 單詞進行演示:h 對應ASCII碼為 104,對應二進制 01101000, i 對應ASCII碼為 105,對應二進制01101001??傋止潝挡荒鼙?code>3整除應該補至能被3整除,由此產生的000000的6位二進制以 Base64編碼 = 表示,如圖所示:

          3. Base64 編碼解碼實現

          在 window 對象中,有兩個方法 btoa()atob()實現編碼和解碼,本文帶你一步步用 js 實現它們的功能。

          在實現之前,先做好一些準備工作。

          • 獲取相應字符 ASCII 碼方法String.charCodeAt(index)
          • 取得Base64對應的字符方法 String.charAt(index)

          假設三個 ASCII 碼為 chr1,chr2,chr3, 如何獲取對應的 base64 索引(enc1,enc2,enc3,enc4)呢?這里就涉及到位運算。

          • >>向右移動,前面補0, 如 104 >> 201101000=> 00011010
          • &與運算,只有兩個操作數相應的比特位都是 1 時,結果才為 1,否則為 0。如 104 & 301101000 & 00000011 => 00000000
          • |或運算,對于每一個比特位,當兩個操作數相應的比特位至少有一個 1 時,結果為 1,否則為 0。如 01101000 | 00000011 => 01101011
          • >>符號移動可以取前n位或者后n位;與運算可以取后幾位,如 104 & 3即取后兩位比特位,104 & 15即取后4位比特位

          位運算的搭配結合,即可獲取相對應的 base64 字符索引

          • enc1 = chr1 >> 2, 取 chr1 的前 6 位即向右移動兩位
          • enc2 = ((chr1 & 3) << 4) | (chr2 >> 4),取 chr1 的后 2 位 + chr2的前 4 位
          • enc3 = ((chr2 & 15) << 2) | (chr3 >> 6),取 chr2 的后 4 位 + chr3的前 2 位
          • enc4 = chr3 & 63, 取 chr3 剩下的后 6 位

          base64 的編碼解碼,其實就是 3 字節與 4 base64字符的相互轉化過程,我們定義兩個方法:encode()decode()

          //?base64?字符,共65個let?_keyStr?=????'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';//?編碼function?encode(input)?{????let?output?=?'',????????i?=?0,????????chr1,????????chr2,????????chr3,????????enc1,????????enc2,????????enc3,????????enc4;????while?(i?<?input.length)?{????????//?首先獲取前三個字符對應的?ASCII?碼????????chr1?=?input.charCodeAt(i++);????????chr2?=?input.charCodeAt(i++);????????chr3?=?input.charCodeAt(i++);????????//?再將這三個字符轉化為?4?個?base64?字符所對應的數字????????//?取第一字符?chr1?的前?6?比特位作為?base64?字符?1?的索引????????enc1?=?chr1?>>?2;????????//?取?chr1?的后2位,在末尾補?chr2?的前?4?位作為?base64?字符?2?的索引????????enc2?=?((chr1?&?3)?<<?4)?|?(chr2?>>?4);????????//?取?chr2?的后?4?位,在末尾補?chr3?的前?2?位作為?base64?字符?3?的索引????????enc3?=?((chr2?&?15)?<<?2)?|?(chr3?>>?6);????????//?取chr3?的后?6?位作為?base64?字符?4?的索引????????enc4?=?chr3?&?63;????????//?判斷是否要補位,即?+?0?,補位則設置索引為?64,對應?‘=’?字符????????if?(Number.isNaN(chr2))?{????????????enc3?=?enc4?=?64;????????}?else?if?(Number.isNaN(chr3))?{????????????enc4?=?64;????????}????????output?=????????????output?+????????????_keyStr.charAt(enc1)?+????????????_keyStr.charAt(enc2)?+????????????_keyStr.charAt(enc3)?+????????????_keyStr.charAt(enc4);????}????return?output;}//?解碼function?decode(input)?{????let?output?=?'',????????i?=?0,????????chr1,????????chr2,????????chr3,????????enc1,????????enc2,????????enc3,????????enc4;????while?(i?<?input.length)?{????????enc1?=?_keyStr.indexOf(input.charAt(i++));????????enc2?=?_keyStr.indexOf(input.charAt(i++));????????enc3?=?_keyStr.indexOf(input.charAt(i++));????????enc4?=?_keyStr.indexOf(input.charAt(i++));????????//?取?enc1?+?enc2?的前2位組成?8?比特位即?1?字節????????chr1?=?(enc1?<<?2)?|?(enc2?>>?4);????????//?取?enc2?后?4?位?+?enc3?的前?4?位組成?8?比特位即?1?字節????????chr2?=?((enc2?&?15)?<<?4)?|?(enc3?>>?2);????????//?取?enc3?前?2?位?+?enc4?組成?8?比特位即?1?字節????????chr3?=?((enc3?&?3)?<<?6)?|?enc4;????????output?=?output?+?String.fromCharCode(chr1);????????//?判斷下是否為?base64?的?=?字符,如果不是才添加????????if?(enc3?!=?64)?{????????????output?=?output?+?String.fromCharCode(chr2);????????}????????if?(enc4?!=?64)?{????????????output?=?output?+?String.fromCharCode(chr3);????????}????}????return?output;}console.log(encode('hello?world'));?//?aGVsbG8gd29ybGQ=console.log(encode('hello?world')?===?btoa('hello?world'));?//?trueconsole.log(decode('aGVsbG8gd29ybGQ='))//?'hello?world'console.log(decode('aGVsbG8gd29ybGQ=')?===?atob('aGVsbG8gd29ybGQ='))?//?true復制代碼

          4. 問題與優化

          在使用的過程中我們發現:當字符不是 ASCII 碼時,或者說 unicode 碼大于255 時,這兩個方法就不適用了,同樣的,window 上的 atob()btoa() 也有這個問題。

          你好這個詞對應的 unicode 分別是 20320 和 22909,其已經遠遠超過 255,可不可以將這 20320 這個數字通過某些方法轉化成多個 0 - 255 之間的數字,解碼的時候也參考同樣的規則解析?試試看唄

          因為 charCodeAt() 返回指定位置的字符的 Unicode 編碼。這個返回值是 0 - 65535 之間的整數, 即 216 - 1, 可以由 16 個比特位數字形容,而一個普通字符是 8 個比特位,所以傳入的字符可以由 1-2 的 8 比特位字符表示。

          這里也有一個問題,就是大字符 = 8比特位數字 * 個數,但是目前個數我們沒有空余位可以存儲,因此 1- 2 個字符是不夠用的,將其增加至 1 - 3 個字符。

          判斷第一個數字,如果大于等于 11100000 即大于224,那么該數字應該轉化為3字符;如果大于等于11000000小于 11100000即≥192且<224,那么該數字應該轉化為 2 字符;剩下的轉化為 1 字符

          function?encodeTransform(input)?{????let?output?=?'';????for?(var?n?=?0;?n?<?input.length;?n++)?{????????var?c?=?input.charCodeAt(n);?//?返回指定位置的字符的?Unicode?編碼。這個返回值是?0?-?65535?之間的整數。????????if?(c?<?128)?{????????????//?0-7位????????????//?如果小于128?即是?ASCII?碼,直接返回該?ASCII?碼????????????output?+=?String.fromCharCode(c);????????}?else?if?(c?>?127?&&?c?<?2048)?{????????????//??8?-?11?位????????????//?這里是將二進制去除后六位,然后在開頭加'11'補至八位二進制,變成一個大于等于192小于224的數字????????????output?+=?String.fromCharCode((c?>>?6)?|?192);????????????//?這里是取二進制后六位,?然后在開頭加'1'補至八位二進制,變成一個小于255大于等于128的數字????????????output?+=?String.fromCharCode((c?&?63)?|?128);????????}?else?{????????????//?12-16位,?因為unicode最大位數為16????????????//?這里是將二進制去除后12位,然后在開頭加'111'補至八位二進制,變成一個大于等于224小于255的數字????????????output?+=?String.fromCharCode((c?>>?12)?|?224);????????????//?這里取?7?-?12?位,然后在開頭加'1'補至八位二進制,變成一個小于192大于等于128的數字????????????output?+=?String.fromCharCode(((c?>>?6)?&?63)?|?128);????????????//?這里取?0?-?6?位,然后在開頭加'1'補至八位二進制,變成一個小于192大于等于128的數字????????????output?+=?String.fromCharCode((c?&?63)?|?128);????????}????}????return?output;}復制代碼

          同樣的,解碼也是一些邊界的判斷以及位運算操作

          function?decodeTransform(input)?{????let?output?=?'',????????i?=?0,????????c?=?(c1?=?c2?=?0);????while?(i?<?input.length)?{????????c?=?input.charCodeAt(i);????????if?(c?<?128)?{????????????//?1字符????????????output?+=?String.fromCharCode(c);????????????i++;????????}?else?if?(c?>?191?&&?c?<?224)?{????????????//?2字符????????????c1?=?input.charCodeAt(i?+?1);????????????output?+=?String.fromCharCode(((c?&?31)?<<?6)?|?(c1?&?63));????????????i?+=?2;????????}?else?{????????????//?3字符????????????c1?=?input.charCodeAt(i?+?1);????????????c2?=?input.charCodeAt(i?+?2);????????????output?+=?String.fromCharCode(????????????????((c?&?15)?<<?12)?|?((c1?&?63)?<<?6)?|?(c2?&?63)????????????);????????????i?+=?3;????????}????}????return?output;}復制代碼

          這里是完整代碼,請點擊查看!

          5. 總結

          這篇文章的起源是:一個朋友讓我給他寫個 base64 轉化的頁面,當時我想都沒想就直接用了 btoa 和 atob. 后來他在用的時候發現中文無法編碼,會出現報錯情況。有點小尷尬,因此去網上找了 base64 的轉化庫,細細的研究它,了解它的原理后發現還是蠻有意思的,涉及到許多位運算和位操作,這部分需要花點心思去理解,也算是有所收獲吧!

          標簽:base64解碼-
          上一篇:IDEA啟動報錯

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          select是什么牌子?Select是丹麥品牌。Selected是世界上最大的時裝集團之一。是凌志時尚著名的商務休閑男裝品牌。1997年在丹麥成立,2008年引入中國市場。Selected在全球25多個國家擁有自己的分店。select是哪個鍵急?打開游戲最上面一行,左邊第三個是“意見”第一個是“模擬設置”點擊彈出框頂部的“控制”“鍵盤”右欄下面有“選擇”,鍵盤上對應的鍵是“選擇”。所有的鑰匙都可以...

          蘋果CEO喬布斯身價多少?世界排第幾?如果是凈值的話,蘋果首席執行官史蒂夫·喬布斯以83億美元的凈值在《福布斯》2011年全球富豪榜上排名第110位。與此同時,喬布斯在美國富豪中排名第34位。喬布斯怎么能持有蘋果一半以上的股份?當喬布斯持有蘋果公司11.3%的650萬股股份時,他在被股東趕出蘋果公司后賣掉了這11.3%的股份?,F在喬布斯回來時持有蘋果公司不到1%的股份,大約550萬美元的股份,只占...

          朋友,們知道北京哪能買到進口奶粉的? ;美國的大商場,像新世界,都有進口食品區~如果沒有 t工作,去友誼商店,那里有進口食品超市~北京哪個區哪個大型超市有進口奶粉?:我家吃的熱海奶粉都是德國原裝罐進口的,一般都是在沃爾瑪、大潤發等實體店買的。北京海淀哪些超市賣奶粉?在北京海淀銷售奶粉的超市包括吳梅、家樂福、美廉美和永輝。優博瑞慕奶粉北京哪里有賣的?:在北京和物美超市都有賣,北京物美超市是北京的連...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>