赞
踩
Base64 在线编码/解码: https://base64.us/
SMTP
传输协议在早期,只能用于传送 7 位的 ASCII
码,而ASCII码就是基于英语设计的,对于非英语国家的文字等资源就无法发送。MIME
,这是一种用于在互联网上传输数据的标准,增加了邮件主题结构,定义了邮件、文本、音频、图像和多媒体文件等非ASCII码的编码传输规则。Base64
是MIME的一种编码方式。MIME
规范中定义了Base64编码作为一种可靠的方式,用于在文本协议中表示二进制数据。通过使用Base64编码,可以将二进制数据转换为可打印字符,从而保证数据在传输过程中不受损失,并且能够被各种文本协议(如SMTP、HTTP)正确处理。MIME
中,当需要在文本协议中传输二进制数据(如邮件附件或图片数据)时,通常会将数据先进行Base64编码,然后将编码后的数据作为文本内容进行传输。Base64
是一种用64个字符(a-z, A-Z, 0-9, +, /)来表示任意二进制数据的方法。
Base64 是一种索引编码,由于 2^6=64,所以每 6 个比特为一个单元,对应某个可打印字符,每个字符都对应一个索引。
索引和打印字符的对应关系如下:
索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 |
---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w |
1 | B | 17 | R | 33 | h | 49 | x |
2 | C | 18 | S | 34 | i | 50 | y |
3 | D | 19 | T | 35 | j | 51 | z |
4 | E | 20 | U | 36 | k | 52 | 0 |
5 | F | 21 | V | 37 | l | 53 | 1 |
6 | G | 22 | W | 38 | m | 54 | 2 |
7 | H | 23 | X | 39 | n | 55 | 3 |
8 | I | 24 | Y | 40 | o | 56 | 4 |
9 | J | 25 | Z | 41 | p | 57 | 5 |
10 | K | 26 | a | 42 | q | 58 | 6 |
11 | L | 27 | b | 43 | r | 59 | 7 |
12 | M | 28 | c | 44 | s | 60 | 8 |
13 | N | 29 | d | 45 | t | 61 | 9 |
14 | O | 30 | e | 46 | u | 62 | + |
15 | P | 31 | f | 47 | v | 63 | / |
Base64 编码要求把 3 个 8 位的字节(3*8=24)转化为 4 个 6 位的字节(4*6=24),之后在 6 位的前面补两个 0,形成 8 位一个字节的形式。 如果剩下的字符不足 3 个字节,则用 0 填充,输出字符使用 =,因此编码后输出的文本末尾可能会出现 1 或 2 个 =。
为了保证所输出的编码位可读字符,Base64 制定了一个编码表,以便进行统一转换。编码表的大小为 2^6=64,这也是 Base64 名称的由来。
ASCII是8位
一个字节,Base64是6位
一个字节,
3个字节的ASCII编码刚好等于4个字节的Base64编码,3 * 8 = 4 * 6 = 24
示例:
you
eW91
ASCII是8位
一个字节,Base64是6位
一个字节,
2个字节的ASCII编码补2位零等于3个字节的Base64编码,不足4个字节的Base64编码使用 = 代替一个字节来补齐,2 * 8 + 2 = 3 * 6 = 18
示例:
yo
eW8=
ASCII是8位
一个字节,Base64是6位
一个字节,
1个字节的ASCII编码补4位零等于2个字节的Base64编码,不足4个字节的Base64编码使用 = 代替一个字节来补齐,1 * 8 + 4 = 2 * 6 = 12
示例:
y
eQ==
UTF-8是8位
一个字节,Base64是6位
一个字节,
UTF-8里中文是三个字节,所以一个UTF-8编码的中文刚好可以转换为4个字节的Base64编码。3 * 8 = 4 * 6 = 24
示例:
中
5Lit
首先,由于系统中默认字符串的编码格式为 unicode
,需要将字符串 中
转换为 utf-8
格式的二进制数组:
/** * 字节数组 转 二进制字符串 * @param bytes 高位 到 低位 * @return 二进制字符串 */ public static String byteToBinStr2(byte[] bytes) { StringBuilder s1 = new StringBuilder(); for (byte aByte : bytes) { s1.append(Long.toBinaryString((aByte & 0xFF) + 0x100).substring(1)); } return s1.toString(); } public static void main(String[] args) { System.out.println(byteToBinStr2("中".getBytes(StandardCharsets.UTF_8))); }
执行结果:
每8位1字节分隔得到:
11100100 10111000 10101101
Base64编码:
使用 jdk 自带的 DatatypeConverter.java
类实现,但是 jdk 版本必须 >= 1.6
。
import java.io.UnsupportedEncodingException;
import javax.xml.bind.DatatypeConverter;
编码:
/** * base64 编码(方法一) * @explain DatatypeConverter.java实现 * @param str 待编码字符串 * @return 编码字符串 */ public static String encode(String str) { // base64字符串 String base64Str = ""; try { // 非字符串才进行编码 if (str != null && str.length() > 0) { // String 转 byte[] byte[] bytes = str.getBytes("utf-8"); // 编码 base64Str = DatatypeConverter.printBase64Binary(bytes); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return base64Str; }
解码:
/** * base解码(方法一) * @explain DatatypeConverter.java实现 * @param base64Str 待解码字符串 * @return 解码字符串 */ public static String decode(String base64Str) { // 解码后的字符串 String str = ""; // 非空字符串才进行解码 if (base64Str != null && base64Str.length() > 0) { // 解码 byte[] base64Bytes = DatatypeConverter.parseBase64Binary(base64Str); try { // byte[] 转 String str = new String(base64Bytes, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return str; }
测试代码:
public static void main(String[] args) {
String s = "y";
String base64Str = encode2(s);
System.out.println("原文:" + s);
System.out.println("base64编码后(方法一):" + base64Str);
System.out.println("base64解码后(方法一):" + decode2(base64Str));
}
执行结果:
使用 jdk 自带的 Base64.java
类实现,但是 jdk 版本必须 >= 1.8
。
import java.util.Base64;
import java.nio.charset.StandardCharsets;
编码:
/** * base64编码(方法二) * @explain Base64.java实现 * @param str 待编码字符串 * @return 编码字符串 */ public static String encode2(String str) { // 非空字符串才进行编码 if (str != null && str.length() > 0) { // String 转 byte[] byte[] bytes = str.getBytes(StandardCharsets.UTF_8); // 编码(base64字符串) return Base64.getEncoder().encodeToString(bytes); } return ""; }
解码:
/** * base64解码(方法二) * @explain Base64.java实现 * @param base64Str 待解码字符串 * @return 解码字符串 */ public static String decode2(String base64Str) { // 非空字符串才进行解码 if (base64Str != null && base64Str.length() > 0) { // 编码 byte[] base64Bytes = Base64.getDecoder().decode(base64Str); // byte[] 转 String(解码后的字符串) return new String(base64Bytes, StandardCharsets.UTF_8); } return ""; }
测试代码:
public static void main(String[] args) {
String s = "y";
String base64Str = encode2(s);
System.out.println("原文:" + s);
System.out.println("base64编码后(方法二):" + base64Str);
System.out.println("base64解码后(方法二):" + decode2(base64Str));
}
执行结果:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.StandardCharsets;
编码:
/** * base64编码(方法三) * @explain commons工具包实现 * @param str 待编码字符串 * @return 编码字符串 */ public static String encode3(String str) { // 非空字符串才进行编码 if (str != null && str.length() > 0) { // String 转 byte[] byte[] bytes = str.getBytes(StandardCharsets.UTF_8); // 编码(base64字符串) return Base64.encodeBase64String(bytes).replaceAll(" \r\n", ""); } return ""; }
解码:
/** * base64解码(方法三) * @explain commons工具包实现 * @param base64Str 待解码字符串 * @return 解码字符串 */ public static String decode3(String base64Str) { // 非空字符串才进行解码 if (base64Str != null && base64Str.length() > 0) { // 解码 byte[] base64Bytes = Base64.decodeBase64(base64Str); // byte[] 转 String(解码后的字符串) return new String(base64Bytes, StandardCharsets.UTF_8); } return ""; }
测试代码:
public static void main(String[] args) {
String s = "y";
String base64Str = encode3(s);
System.out.println("原文:" + s);
System.out.println("base64编码后(方法三):" + base64Str);
System.out.println("base64解码后(方法三):" + decode3(base64Str));
}
执行结果:
执行结果:方法一、方法二、方法三一致
效率:快–>慢:方法二 > 方法一 > 方法三
因此,如果项目用的是 jdk1.8
,最佳选择是方法二;jdk1.6
,最佳选择是方法一。
JavaScript 提供了两个原生的方法,用来处理Base64编码:btoa()
和 atob()
btoa()
:Base64编码。atob()
:Base64解码。以上两个方法如果操作的字符串不是 ASCII 编码会报错:
例如:btoa('中')
VM707:1 Uncaught DOMException: Failed to execute ‘btoa’ on ‘Window’: The string to be encoded contains characters outside of the Latin1 range.
可以使用这两个方法,将非ASCII码的字符作为URI组件进行编码,然后再进行Base64编码。
encodeURIComponent()
:作为URI组件进行编码。decodeURIComponent()
:作为URI组件进行解码。综上所述,适用于所有情况(ASCII码+非ASCII码)的Base64编解码方法如下:
btoa(encodeURIComponent(待编码内容))
:Base64 编码。decodeURIComponent(atob(待解码内容))
:Base64 解码。注意:这种方法和UTF-8格式的加密不能通用。
执行结果:
整理完毕,完结撒花~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。