今天就跟大家聊聊有關(guān)如何分析JavaScrip中的Base64編碼和解碼,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
成都創(chuàng)新互聯(lián)公司是專業(yè)的崇州網(wǎng)站建設(shè)公司,崇州接單;提供成都網(wǎng)站設(shè)計、做網(wǎng)站,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行崇州網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!
Base64是最常用的編碼之一,比如開發(fā)中用于傳遞參數(shù)、現(xiàn)代瀏覽器中的標(biāo)簽直接通過Base64字符串來渲染圖片以及用于郵件中等等。Base64編碼在RFC2045中定義,它被定義為:Base64內(nèi)容傳送編碼被設(shè)計用來把任意序列的8位字節(jié)描述為一種不易被人直接識別的形式。
我們知道,任何數(shù)據(jù)在計算機中都是以二進(jìn)制的方式存儲的。一個字節(jié)為8位,一個字符在計算機中存儲為一個或多個字節(jié),比如英文字母、數(shù)字以及英文標(biāo)點符號就是用一個 字節(jié)來存儲的,通常稱為ASCII碼。而簡體中文、繁體中文、日文以及韓文等都是用多字節(jié)來存儲的,通常稱為多字節(jié)字符。因為Base64編碼是對字符串的編碼表示進(jìn)行處理的,不同編碼的字符串的Base64的結(jié)果是不同的,所以我們需要了解基本的字符編碼知識。
計算機最開始只支持ASCII碼,一個字符用一個字節(jié)表示,只用了低7位,***位為0,因此總共有128個ASCII碼,范圍為0~127。后來為了支持多種地區(qū)的語言,各大組織機構(gòu)和IT廠商開始發(fā)明它們自己的編碼方案,以便彌補ASCII編碼的不足,如GB2312編碼、GBK編碼和Big5編碼等。但這些編碼都只是針對局部地區(qū)或少數(shù)語言文字,沒有辦法表達(dá)所有的語言文字。而且這些不同的編碼之間并沒有任何聯(lián)系,它們之間的轉(zhuǎn)換需要通過查表來實現(xiàn)。
為了提高計算機的信息處理和交換功能,使得世界各國的文字都能在計算機中處理,從1984年起,ISO組織就開始研究制定一個全新的標(biāo)準(zhǔn):通用多八位(即多字節(jié))編碼字符集(Universal Multiple-Octet Coded Character Set),簡稱UCS。標(biāo)準(zhǔn)的編號為:ISO 10646。這一標(biāo)準(zhǔn)為世界各種主要語言的字符(包括簡體及繁體的中文字)及附加符號,編制統(tǒng)一的內(nèi)碼。
統(tǒng)一碼(Unicode)是Universal Code的縮寫,是由另一個叫“Unicode學(xué)術(shù)學(xué)會”(The Unicode Consortium)的機構(gòu)制定的字符編碼系統(tǒng)。Unicode與ISO 10646國際編碼標(biāo)準(zhǔn)從內(nèi)容上來說是同步一致的。具體可參考:Unicode 。
ANSI
ANSI不代表具體的編碼,它是指本地編碼。比如在簡體版windows上它表示GB2312編碼,在繁體版windows上它表示Big5編碼,在日文操作系統(tǒng)上它表示JIS編碼。所以如果您新建了個文本文件并保存為ANSI編碼,那么您現(xiàn)在應(yīng)該知道這個文件的編碼為本地編碼。
Unicode
Unicode編碼是和字符表一一映射的。比如56DE代表漢字'回',這種映射關(guān)系是固定不變的。通俗的說Unicode編碼就是字符表的坐標(biāo),通過56DE就能找到漢字'回'。Unicode編碼的實現(xiàn)包括UTF8、UTF16、UTF32等等。
Unicode本身定義的就是每個字符的數(shù)值,是字符和自然數(shù)的映射關(guān)系,而UTF-8或者UTF-16甚至UTF-32則定義了如何在字節(jié)流中斷字,是計算機領(lǐng)域的概念。
通過上圖我們知道,UTF-8編碼為變長的編碼方式,占1~6個字節(jié),可通過Unicode編碼值的區(qū)間來判斷,并且每個組成UTF8字符的字節(jié)都是有規(guī)律可循的。本文只討論UTF8和UTF16這兩種編碼。
UTF16
UTF16編碼使用固定的2個字節(jié)來存儲。因為是多字節(jié)存儲,所以它的存儲方式分為2種:大端序和小端序。UTF16編碼是Unicode最直接的實現(xiàn)方式,通常我們在windows上新建文本文件后保存為Unicode編碼,其實就是保存為UTF16編碼。UTF16編碼在windows上采用小端序的方式存儲,以下我新建了個文本文件并保存為Unicode編碼來測試,文件中只輸入了一個漢字'回',之后我用Editplus打開它,切換到十六進(jìn)制方式查看,如圖所示:
我們看到有4個字節(jié),前2個字節(jié)FF FE是文件頭,表示這是一個UTF16編碼的文件,而DE 56則是'回'的UTF16編碼的十六進(jìn)制。我們經(jīng)常使用的JavaScript語言,它內(nèi)部就是采用UTF16編碼,并且它的存儲方式為大端序,來看一個例子:
很明顯跟剛才Editplus顯示的不一樣,順序是相反的,這是因為字節(jié)序不一樣。具體可參考:UTF-16 。
UTF8
UTF8是采用變長的編碼方式,為1~6個字節(jié),但通常我們只把它看作單字節(jié)或三字節(jié)的實現(xiàn),因為其它情況實在少見。UTF8編碼通過多個字節(jié)組合的方式來顯示,這是計算機處理UTF8的機制,它是無字節(jié)序之分的,并且每個字節(jié)都非常有規(guī)律,詳見上圖,在此不再詳述。
UTF16轉(zhuǎn)UTF8
UTF16和UTF8之間的相互轉(zhuǎn)換可以通過上圖的轉(zhuǎn)換表來實現(xiàn),判斷Unicode碼所在的區(qū)間就可以得到這個字符是由幾個字節(jié)所組成,之后通過移位來實現(xiàn)。我們用漢字'回'來舉一個轉(zhuǎn)換的例子。
我們已經(jīng)知道漢字'回'的Unicode碼是0x56DE,它介于U+00000800 – U+0000FFFF之間,所以它是用三個字節(jié)來表示的。
所以我們需要將0x56DE這個雙字節(jié)的值變?yōu)槿止?jié)的值,注意上圖中的x部分,就是對應(yīng)0x56DE的各位字節(jié),如果您數(shù)一下x的個數(shù),會發(fā)現(xiàn)剛好是16位。
轉(zhuǎn)換思路
從0x56DE中取出4位放在低位,并和二進(jìn)制的1110結(jié)合,這就是***個字節(jié)。從0x56DE中剩下的字節(jié)中取出6位放在低位,并和二進(jìn)制的10結(jié)合,這就是第二個字節(jié)。第三個字節(jié)依照類似的方式實現(xiàn)。
代碼實現(xiàn)
為了讓大家更好的理解,以下代碼只是實現(xiàn)漢字'回'的轉(zhuǎn)換,代碼如下:
輸出的結(jié)果看起來像亂碼,這是因為JavaScript不知道如何顯示UTF8的字符。您或許會說輸出不正常轉(zhuǎn)換還有什么用,但您應(yīng)該知道轉(zhuǎn)換的目的還經(jīng)常用于傳輸或API的需要。
UTF8轉(zhuǎn)UTF16
這是UTF16轉(zhuǎn)換到UTF8的逆轉(zhuǎn)換,同樣需要對照轉(zhuǎn)換表來實現(xiàn)。還是接上一個例子,我們已經(jīng)得到了漢字'回'的UTF8編碼,這是三個字節(jié)的,我們只需要按照轉(zhuǎn)換表來轉(zhuǎn)成雙字節(jié)的,如圖所示,我們需要保留下所有的x。
代碼如下:
知道了轉(zhuǎn)換規(guī)則,就很容易實現(xiàn)了。
Base64編碼要求把3個8位字節(jié)(3*8=24)轉(zhuǎn)化為4個6位的字節(jié)(4*6=24),之后在6位的前面補兩個0,形成8位一個字節(jié)的形式。由于2的6次方為64,所以每6個位為一個單元,對應(yīng)某個可打印字符。當(dāng)原數(shù)據(jù)不是3的整數(shù)倍時,如果***剩下兩個輸入數(shù)據(jù),在編碼結(jié)果后加1個“=;如果***剩下一個輸入數(shù)據(jù),編碼結(jié)果后加2個“=;如果沒有剩下任何數(shù)據(jù),就什么都不要加,這樣才可以保證資料還原的正確性。
轉(zhuǎn)碼對照表
每6個單元高位補2個零形成的字節(jié)位于0~63之間,通過在轉(zhuǎn)碼表中查找對應(yīng)的可打印字符?!?”用于填充。如下圖所示為轉(zhuǎn)碼表。
具體可參考: Base64 。
解碼是編碼的逆過程,先看后面補了幾個“=”號,最多只可能補2個“=”號。一個“=”相當(dāng)于補了2個0,所以去掉后面補的0后,再按8位展開,即可還原。
之前已經(jīng)詳細(xì)講解了整個過程,本文的例子都是采用UTF8編碼的字符串作為Base64編碼的基礎(chǔ)。因為JavaScript內(nèi)部是使用Unicode編碼,所以需要有個轉(zhuǎn)換過程,原理之前也詳細(xì)講解過并給出了示例,以下是代碼實現(xiàn):
不得不說,在JavaScript中實現(xiàn)確實很麻煩。我們來看下PHP對同樣的字符串編碼的結(jié)果:
因為字符編碼是一樣的,所以結(jié)果也一樣。
看完上述內(nèi)容,你們對如何分析JavaScrip中的Base64編碼和解碼有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。