Base64编解码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Base64编解码
一、编码原理
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。编码后的数据比原来的数据略长,是原来的4/3倍。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中而不同(Base64de 编码表如下所示)。Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email,email via MIME, 在XML中存储复杂数据.
Base64编码表
二、编码流程
步骤1:将要编码的所有字符都转化成对应的ASCII码。
步骤2:将所有的ASCII码转换成对应的8位长的二进制数。
步骤3:将所得的二进制数从高位到低位开始分成6位一组,最后一组不足六的则补充0
步骤4:将每组二进制数转换成十进制数,然后对照base64的编码表查找得到相应的编码。
注意:1、要求被编码字符是8bit的,所以须在ASCII编码范围内,\u0000-\u00ff,中文就不行。
2、如果被编码的字符串中字符的个数为3的倍数,按照上面的步骤即可得到正确的base64编码。但是如果不是3的倍数则要分情况讨论。如果是3的倍数余1,则要在编好的码字后面加上两个“=”,如果是3的倍数余2,这要在编好的码字后面加上一个“=”。(例如w的base64编码为dw==,w1的base64编码为dzE=)
下面我们来对具体的字符串进行编码举例,以便更好的理解编码流程:
编码「Man」
在此例中,Base64算法将三个字符编码为4个字符
特殊情况
A的编码为QQ= =
BC的编码为QkM=
三、核心算法程序
算法的基本原理如下:由于每次转换都需要6个bit,而这6个bit可能都来自一个字节,也可以来自前后相临的两个字节。定义两个变量:prevByteBitCount和nextByteBitCount,这两个变量分别表述从前一个和后一个节字取得的bit数。如果prevByteBitCount为0,表示6个bit全部来自下一个字节的高6位。如果nextByteBitCount = 0,表示6个bit全部来自前一个字节的低6位。最后通过适当的移位获得所需要的6个bit,再在上面的base64编码表中查找相应的字符。算法的实现代码如下:
public static String encoder(byte[] bytes)
{
StringBuilder result = new StringBuilder();
String base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // prevByteBitCount表示从前一个字节取得的bit数,nextByteBitCount表示从后一个字节取得的bit数
int prevByteBitCount = 0, nextByteBitCount = 6;
// i表示当前的数组索引,n表示已经处理的位数
int i = 0, n = 0;
// byteCount表示总的位数
int byteCount = 8 * bytes.length;
byte b = 0;
while (true)
{
// 处理从前后两个字节取得位数的情况
if (prevByteBitCount > 0 && nextByteBitCount > 0)
{
// 将前一个字节的低位向左移nextByteBitCount个bit,并使下一个字节的高位(nextByteBitCount指定的位数)右移到字节的最低位,
// 然后将两个位移结果进行逻辑或,也就是将从前一个字节和后一个字节取得的相应的bit合并为一个字节的低位
b = (byte) (((0xff & bytes[i]) << nextByteBitCount) | ((0xff & bytes[i + 1]) >> (8 - nextByteBitCount)));
// 将逻辑或后的结果的最高两个bit置成0
b = (byte) (b & 0x3f);
prevByteBitCount = 8 - nextByteBitCount;
nextByteBitCount = 6 - prevByteBitCount;
}
// 处理从后一个字节取得高6位的情况
else if (prevByteBitCount == 0)
{
// 后一个字节的高6位右移动低6位
b = (byte) ((0xff & bytes[i]) >> (8 - nextByteBitCount));
// 处理后面的位时,就是从前一个字节取2个bit,从后一个字字取4个bit prevByteBitCount = 2;
nextByteBitCount = 4;
}
// 处理从前一个字节取得低6位的情况
else if (nextByteBitCount == 0)
{
// 将前一个字节的最高两个bit置成0
b = (byte) (0x3f & bytes[i]);
// 处理后面的位时,从后一个字节取6个bit
prevByteBitCount = 0;
nextByteBitCount = 6;
}
result.append(base64.charAt(b));
n += 6;
i = n / 8;
int remainBitCount = byteCount - n;
if (remainBitCount < 6)
{
// 将剩余的bit补0后,仍然需要在base64编码表中查找相应的字符,并添加到结果字符串的最后
if (remainBitCount > 0)
{
b = bytes[bytes.length - 1];
b = (byte) (0x3f & (b << (6 - remainBitCount)));
result.append(base64.charAt(b));
}
break;
}
}
// 如果总bit数除3的余数为1,加一个“=”,为2,加两个“=”
n = byteCount % 3;
for (i = 0; i < n; i++)
result.append("=");
return result.toString();
}
对于程序的理解:这个程序应该只是总程序的一部分,它主要实现了对二进