当前位置: 首页 > 科技观察

JavaScript:Base64编码解码详解

时间:2023-03-13 12:41:13 科技观察

Base64是最常用的编码之一,比如开发中用于传递参数,现代浏览器中的标签直接通过Base64字符串渲染图片,以及用于邮件等。等待。Base64编码在RFC2045中定义,其定义为:Base64内容传输编码旨在将任意8位字节序列描述成人类不易识别的形式。我们知道,任何数据在计算机中都是以二进制形式存储的。一个字节为8位,一个字符在计算机中存储为一个或多个字节。例如,英文字母、数字、英文标点符号存储在一个字节中,通常称为ASCII码。简体中文、繁体中文、日文、韩文都是以多字节字符存储的,通常称为多字节字符。因为Base64编码处理的是字符串的编码表示,不同编码字符串的Base64结果是不同的,所以我们需要了解基本的字符编码知识。基本字符编码计算机一开始只支持ASCII码。一个字符用一个字节表示,只用低7位,最后一位为0。所以ASCII码一共有128个,从0到127。后来为了支持语言在多个地区、各大机构和IT厂商开始发明自己的编码方案来弥补ASCII编码的不足,如GB2312编码、GBK编码、Big5编码等。但是,这些代码只是针对局部地区或少数几种语言,并没有办法表达所有的语言。而且这些不同的编码之间没有联系,它们之间的转换需要通过查表的方式来实现。为了提高计算机的信息处理和交换功能,使世界各国的文字都能在计算机中处理,从1984年开始,ISO组织开始研究制定新的标准:通用多字节(即多字节)编码字符集(UniversalMultiple-OctetCodedCharacterSet),简称UCS。标准的编号为:ISO10646。该标准为世界上各种主要语言的字符(包括简体和繁体汉字)和附加符号编制了统一的内码。万国码(Unicode)是UniversalCode的缩写,是由另一个名为“统一码学术协会”(TheUnicodeConsortium)的组织开发的字符编码系统。Unicode与ISO10646国际编码标准在内容上是同步一致的。详情请参考:Unicode。ANSIANSI不代表特定的编码,它指的是本地编码。比如windows简体版是GB2312编码,windows繁体版是Big5编码,日文操作系统是JIS编码。因此,如果您创建了一个新的文本文件并将其保存为ANSI编码,那么您现在应该知道该文件的编码是本地编码。UnicodeUnicode编码是与字符表的一对一映射。比如56DE代表汉字“会”,这个映射关系是固定的。通俗地说,Unicode编码就是字符表的坐标,通过56DE就可以找到汉字“回”。Unicode编码的实现包括UTF8、UTF16、UTF32等。Unicode本身定义了每个字符的值,是字符和自然数的映射关系,而UTF-8或者UTF-16甚至UTF-32定义了如何在字节流中打断字符,这是计算机中的一个概念场地。从上图我们知道UTF-8编码是一种变长编码方式,占1到6个字节,可以通过Unicode编码取值范围来判断,组成UTF8字符的每个字节都有规则跟随。本文只讨论UTF8和UTF16这两种编码。UTF16UTF16编码使用固定的2个字节来存储。因为是多字节存储,所以它的存储方式分为big-endian和little-endian两种。UTF16编码是Unicode最直接的实现。通常,我们在Windows上新建一个文本文件,并将其保存为Unicode编码。其实就是保存为UTF16编码。UTF16编码在Windows上以小端存储。下面我新建了一个文本文件,保存为Unicode编码进行测试。档案中只输入了一个汉字“会”。之后用Editplus打开,切换到十六。二进制查看,如图:我们看到有4个字节,前2个字节FFFE是文件头,说明这是一个UTF16编码的文件,DE56是'back'的UTF16编码的十六进制。我们经常使用的JavaScript语言,内部使用的是UTF16编码,其存储方式是big-endian。让我们看一个例子:和Editplus刚才显示的明显不一样,顺序颠倒了,这是因为字节顺序不一样。具体可以参考:UTF-16。UTF8UTF8采用变长编码方式,为1~6个字节,但通常我们只将其视为单字节或三字节实现,因为其他情况很少见。UTF8编码是通过多个字节的组合来显示的。这是计算机处理UTF8的机制。它没有字节顺序,每个字节都很有规律。具体见上图,这里不再赘述。UTF16与UTF8的相互转换UTF16转UTF8UTF16与UTF8的相互转换可以通过上图中的转换表来实现。判断Unicode码所在的区间可以得到字符是由几个字节组成的,然后通过移位来实现。我们用汉字“回”来举一个转换的例子。我们已经知道汉字“回”的Unicode编码是0x56DE,介于U+00000800–U+0000FFFF之间,所以用三个字节来表示。所以我们需要把0x56DE的双字节值改成三字节值。注意上图中x部分对应的是0x56DE的每个字节。如果你数一下x的个数,你会发现正好是16位。转换思路从0x5??6DE中取出4位放在低位,与二进制1110组合,即第一个字节。从0x56DE中剩余的字节中取出6位放在低位,与二进制10组合,这就是第二个字节。第三个字节以类似的方式实现。代码实现为了让大家更好的理解,下面的代码只是实现汉字‘回’的转换,代码如下:输出看起来像乱码,因为JavaScript不知道如何显示UTF8字符。你可能会说输出没有正常转换,但你应该知道转换的目的往往是为了传输或者API需要。UTF8转UTF16这是UTF16到UTF8的逆转换,同样需要参考转换表来实现。还是继续举个例子,我们已经得到汉字'hui'的UTF8编码,是三个字节,我们只需要根据转换表将其转换成双字节即可,如图,我们需要保留所有x。代码如下:知道了转换规则,就很容易实现了。Base64编码Base64编码需要将3个8位字节(3*8=24)转换成4个6位字节(4*6=24),然后在6位前面加上两个0,组成8位,形式为一个字节。由于2的6次方为64,所以每6位为一个单位,对应于某个可打印的字符。当原始数据不是3的整数倍时,如果只剩下两个输入数据,则在编码结果后加1个“=”;如果只剩下一个输入数据,则在编码结果后加2个“=”;如果没有剩余数据,则不要添加任何内容,以确保数据恢复的正确性。转码对照表每6个单元的高位加2个0组成的字节在0~63之间,在转码表中查找对应的可打印字符。“=”用于填充。转换表如下图所示。详情请参考:Base64。#p#Base64解码解码是编码的逆过程。先看后面加了多少个“=”号。最多只能加2个“=”号。一个“=”相当于加了2个??0,所以去掉后面的0,再扩展8位,就可以恢复了。整个过程在JavaScript实现Base64的编解码之前已经详细讲解过了。本文示例均使用UTF8编码的字符串作为Base64编码的基础。因为JavaScript内部使用Unicode编码,所以需要有一个转换过程。前面已经详细解释了原理,并给出了一个例子。下面是代码实现:不得不说,用JavaScript实现真的很简单我们来看看PHP对同一个字符串进行编码的结果:因为字符编码相同,所以结果是一样的。原文链接:http://my.oschina.net/goal/blog/201032