Base64 编码和解码

什么是 Base64 编码?

Base64 编码是使用 64 个可打印 ASCII 字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成 ASCII 字符串;另外,还有一个 “=” 符号用作填充。

Base64 将输入字符串按字节切分,取得每个字节对应的二进制值(若不足 8 比特则高位补 0),然后将这些二进制数值串联起来,再按照 6 比特一组进行切分(因为 2^6 = 64),最后一组若不足 6 比特则末尾补 0。将每组二进制值转换成十进制,然后在 Base64 字符映射表格中找到对应的符号并串联起来就是 Base64 编码结果。

由于二进制数据是按照 8 比特一组进行传输,因此 Base64 按照 6 比特一组切分的二进制数据必须是 24 比特的倍数(6 和 8 的最小公倍数)。24 比特就是 3 个字节,如果不足 3 字节,则使用 “=” 进行填充。如下:

  • 若最后一组只有 1 个输入数据,则在编码结果后加 2 个=;

  • 若最后一组只有 2 个输入数据,则在编码结果后加 1 个 =。

Commons Codec 实现

在 Apache Commons Codec 库中,提供了 Base64、Base64InputStream 和 Base64OutputStream 三个类实现 base64 编码和解码。

Base64 类

该类提供了 RFC2045 中定义的 Base64 编码的编码和解码功能,且该类还是线程安全的。此类实现了 RFC2045 中的第 6.8 节(Content-Transfer-Encoding)。

可以使用各种构造函数以以下方式对类进行参数化:

  • URL安全模式:默认关闭

  • 行长:默认为76

  • 行分隔符:默认为CRLF(“\r\n”)

URL安全参数仅适用于编码操作。解码可无缝处理两种模式。

由于此类直接在字节流而不是字符流上运行,因此它被硬编码为仅编码/解码与较低的 127 个 ASCII 兼容的字符编码(ISO-8859-1,Windows-1252,UTF-8 等等)

构造方法说明

public Base64(int lineLength,
              byte[] lineSeparator,
              boolean urlSafe,
              CodecPolicy decodingPolicy)

创建用于解码(所有模式)和 URL 不安全模式下编码的 Base64 编解码器。编码时,在构造函数中给出了行长和行分隔符,编码表为STANDARD_ENCODE_TABLE。参数说明:

  • lineLength:每行编码数据最多为给定长度(四舍五入为最接近的 4 的倍数)。如果 lineLength <= 0,则输出将不会分为几行。

  • lineSeparator:每一行编码数据将以此字节序列结尾。

  • urlSafe:我们将使用 “-” 和 “_” 字符分别替换 “+” 和 “/” 字符。urlSafe 参数仅仅适用于编码操作,解码可无缝处理两种模式。 注意:使用网址安全字母时,不会添加任何填充。

  • decodingPolicy:指定解码策略。

方法说明:

  • static byte[] decodeBase64(byte[] base64Data) 将给定的数据 base64 解码

  • static byte[] decodeBase64(String base64String)

  • static BigInteger decodeInteger(byte[] pArray) 根据诸如W3C的XML签名之类的加密标准对byte64编码的整数进行解码。

  • static byte[] encodeBase64(byte[] binaryData) 使用base64算法对二进制数据进行编码,但不对输出进行分块。

  • static String encodeBase64String(byte[] binaryData)

  • static byte[] encodeBase64(byte[] binaryData, boolean isChunked) 使用base64算法对二进制数据进行编码,可以选择将输出分块为76个字符块。

  • static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe)

  • static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize)

  • static byte[] encodeBase64Chunked(byte[] binaryData)

  • static byte[] encodeBase64URLSafe(byte[] binaryData) 使用base64算法的URL安全变体对二进制数据进行编码,但不对输出进行分块。

  • static String encodeBase64URLSafeString(byte[] binaryData)

  • static byte[] encodeInteger(BigInteger bigInteger) 根据诸如W3C的XML签名之类的加密标准将其编码为byte64编码的整数。

  • boolean isBase64(String base64) 测试给定的String,以查看它是否仅包含Base64字母内的有效字符。

  • boolean isBase64(byte octet)

  • boolean isBase64(byte[] arrayOctet) 测试给定的字节数组,以查看它是否仅包含Base64字母内的有效字符。

  • boolean isInAlphabet(byte octet) 返回 octet 参数是否在 Base64 字母表中

  • boolean isUrlSafe() 返回当前的编码模式

实例

(1)Base64类简单实用

Base64 base64 = new Base64();
byte[] bytes = base64.encode("hello world".getBytes());
System.out.println(new String(bytes));

输出结果:

aGVsbG8gd29ybGQ=

(2)Base64类编码和解码

Base64 base64 = new Base64();
byte[] bytes = base64.encode("hello world".getBytes());
String encodeResult = new String(bytes);
System.out.println( encodeResult );
System.out.println( new String(base64.decode(encodeResult)) );

输出结果:

aGVsbG8gd29ybGQ=
hello world

(3)指定行长度和换行符

Base64 base64 = new Base64(10, "##".getBytes());
byte[] bytes = base64.encode("administrator".getBytes());
System.out.println( new String(bytes) );

输出结果:

YWRtaW5p##c3RyYXRv##cg==##

(4)实用 URL 安全的 Base64 编码和解码

System.out.println("加密数据:");
// 加密数据,返回字节数组
System.out.println(new String(Base64.encodeBase64("hello world".getBytes())));
// 加密数据,返回字符串
System.out.println(Base64.encodeBase64String("hello world".getBytes()));
// 使用 Base64 算法的 URL 安全变体对二进制数据进行编码,但不对输出分块。
// URL 安全的变体输出 - 和 _ 而不是 + 和 / 字符。
// 注意:不添加填充物,即 =。
System.out.println(new String(Base64.encodeBase64URLSafe("hello world".getBytes())));
System.out.println(Base64.encodeBase64URLSafeString("hello world".getBytes()));
System.out.println("解密数据:");
String encodeStr = "aGVsbG8gd29ybGQ=";
// 解密数据,接收字符串参数
System.out.println(new String(Base64.decodeBase64(encodeStr)));
// 解密数据,接收字节数组参数
System.out.println(new String(Base64.decodeBase64(encodeStr.getBytes())));

输出结果:

加密数据:
aGVsbG8gd29ybGQ=
aGVsbG8gd29ybGQ=
aGVsbG8gd29ybGQ
aGVsbG8gd29ybGQ
解密数据:
hello world
hello world

Base64InputStream 类

该类以流的方式(大小不受限制)提供 Base64 编码和解码。编码时,默认的 lineLength 为 76 个字符,默认的 lineEnding 为 CRLF,但是可以使用适当的构造函数来覆盖这些字符。

Base64InputStream 的默认行为是 DECODE(解码),而 Base64OutputStream 的默认行为是 ENCODE(编码),也可以使用其他构造函数来覆盖此行为。实例:

String source = "aGVsbG8gd29ybGQ=";
ByteArrayInputStream inputStream = new ByteArrayInputStream(source.getBytes());
Base64InputStream base64InputStream = new Base64InputStream(inputStream);
// 从 read 方法读取,直接解码
byte[] buffer = new byte[1024];
int len = base64InputStream.read(buffer);
System.out.println(new String(buffer, 0, len));

输出结果:

hello world

Base64OutputStream 类

该类以流的方式(大小不受限制)提供 Base64 编码和解码。编码时,默认的 lineLength 为 76 个字符,默认的 lineEnding 为 CRLF,但是可以使用适当的构造函数来覆盖这些字符。

Base64OutputStream 的默认行为是 ENCODE(编码),而 Base64InputStream 的默认行为是 DECODE(解码)。但是可以通过使用其他构造函数来覆盖此行为。实例:

String source = "hello world";
ByteOutputStream outputStream = new ByteOutputStream();
Base64OutputStream base64OutputStream = new Base64OutputStream(outputStream);
base64OutputStream.write(source.getBytes());
base64OutputStream.close();

// 获取编码结果
String result = new String(outputStream.getBytes());
System.out.println(result);

输出结果:

aGVsbG8gd29ybGQ=

查看 Base64 类的详细用法,请参考官网 API 文档,地址如下:

http://commons.apache.org/proper/commons-codec/apidocs/index.html


说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号