Java8 教程

Java8 内置 Base64 编码支持

Java8 终于官方提供了 Base64 编码/解码的支持(见 java.util.Base64 类)。该类完全由静态方法组成,用于获取 Base64 编码方案的编码器和解码器。该类的实现支持 RFC 4648 和 RFC 2045 中指定的以下 Base64 类型。

  • Basic:使用 RFC 4648 和 RFC 2045 表 1 中指定的 “Base64字母表” 进行编码和解码操作。编码器不添加任何换行(分隔符)字符。解码器拒绝包含 Base64 字母表以外字符的数据。

  • URL和文件名安全:使用 RFC 4648 表 2 中指定的 “URL 和文件名安全 Base64 字母表” 进行编码和解码。编码器不添加任何换行(行分隔符)字符。解码器拒绝包含 Base64 字母表以外字符的数据。

  • MIME:使用 RFC 2045 表 1 中指定的 “Base64字母表” 进行编码和解码操作。编码输出必须以每行不超过 76 个字符的行表示,并使用回车符 “\r” 和紧跟其后的换行符 “\n” 作为行分隔符。编码输出的末尾不添加分隔符。在解码操作中,所有分隔符或其他不在 base64 字母表中的字符都将被忽略。

什么是Base64编码?

Base64 编码可以将一组字节序列编码为一个可打印的 ASCII 字符序列。它经常用于电子邮件消息中的二进制数据,以及 “基本的” HTTP 认证。在过去的很多年中,JDK 都只有一个未公开的类 java.util.prefs.Base64, 以及一个没有文档描述的类 sun.misc.BASE64Encoder。终于,Java8 提供了一个标准的编码器和解码器。

Base64 编码使用 64 个字符来编码 6bit 信息:

  • 26 个大写字母 A-Z。

  • 26 个小写字母 a-z。

  • 10 个数字 0-9。

  • 2 个符号 + 和 - 或者 - 和 _ (对于 URL 和文件名来说都是安全的)。

一般来说,编码后的字符串没有换行符,但是电子邮件使用的 MIME 标准要求每 76 个字符要使用一个 "\r\n" 换行符。

Basic 用法

要进行 Base64 编码,可以使用 Base64 类的静态方法 getEncoder, getUrlEncoder, 或者 getMimeEncoder 来获得一个 Base64.Encoder 对象。该类包含了用来对字符数组或者 NIO ByteBuffer 进行编码的方法。例如:

package com.hxstrive.jdk8.base64;

import java.util.Base64;

public class Base64Demo1 {

    public static void main(String[] args) {
        String str = "Hello World!";
        Base64.Encoder encoder = Base64.getEncoder();

        // 编码
        byte[] result = encoder.encode(str.getBytes());
        System.out.println(new String(result)); //SGVsbG8gV29ybGQh

        // 编码(字符串)
        String result2 = encoder.encodeToString(str.getBytes());
        System.out.println(result2); //SGVsbG8gV29ybGQh
    }

}

另外,你可以使用 wrap 方法去 “包装” 一个输出流,这样所有发送给包装流的数据都会自动进行编码。例如,对 ByteArrayOutputStream 进行包装,将所有数据输入到包装后的 OutputStream 中,最后从 ByteArrayOutputStream 中获取编码后的数据,代码如下:

Base64.Encoder encoder = Base64.getEncoder();
// 包装一个输出流
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
OutputStream outputStream = encoder.wrap(byteArrayOutputStream);

// 写入数据到输出流中
String str = "Hello World!";
// 注意:写入到包装流中,它是对我们的 ByteArrayOutputStream 进行包装
outputStream.write(str.getBytes());

// 依然从 ByteArrayOutputStream 中获取数据,而不是包装流
System.out.println(new String(byteArrayOutputStream.toByteArray()));
// SGVsbG8gV29ybGQh

如果要进行 Base64 解码,只需将这些操作颠倒过来,例如:

Base64.Decoder decoder = Base64.getDecoder();
byte[] result = decoder.decode("SGVsbG8gV29ybGQh");
System.out.println(new String(result)); // Hello World!

byte[] reuslt2 = decoder.decode("SGVsbG8gV29ybGQh".getBytes());
System.out.println(new String(reuslt2)); // Hello World!

或者

Base64.Decoder decoder = Base64.getDecoder();
// 包装流
InputStream input = decoder.wrap(new ByteArrayInputStream("SGVsbG8gV29ybGQh".getBytes()));
// 从包装流读取解码的数据
BufferedInputStream in = new BufferedInputStream(input);
byte[] buffer = new byte[in.available()];
if(-1 != in.read(buffer, 0, buffer.length)) {
    System.out.println(new String(buffer)); // Hello World!
}

URL和文件名安全用法

简单用法如下:

String str = "https://www.hxstrive.com";
// 编码
Base64.Encoder encoder = Base64.getUrlEncoder();
byte[] encoderResult = encoder.encode(str.getBytes());
System.out.println("编码结果:" + new String(encoderResult));
//编码结果:aHR0cHM6Ly93d3cuaHhzdHJpdmUuY29t

// 解码
Base64.Decoder decoder = Base64.getUrlDecoder();
byte[] decoderResult = decoder.decode(encoderResult);
System.out.println("解码结果:" + new String(decoderResult));
//解码结果:https://www.hxstrive.com

MIME用法

简单用法如下:

String str = "使用 RFC 4648 表 2 中指定的 “URL 和文件名安全 Base64 字母表” 进行编码和解码。" +
        "编码器不添加任何换行(行分隔符)字符。解码器拒绝包含 Base64 字母表以外字符的数据。";
// 编码
Base64.Encoder encoder = Base64.getMimeEncoder();
byte[] encoderResult = encoder.encode(str.getBytes());
System.out.println("编码结果:" + new String(encoderResult));
//编码结果:5L2/55SoIFJGQyA0NjQ4IOihqCAyIOS4reaMh+WumueahCDigJxVUkwg5ZKM5paH5Lu25ZCN5a6J
//5YWoIEJhc2U2NCDlrZfmr43ooajigJ0g6L+b6KGM57yW56CB5ZKM6Kej56CB44CC57yW56CB5Zmo
//5LiN5re75Yqg5Lu75L2V5o2i6KGM77yI6KGM5YiG6ZqU56ym77yJ5a2X56ym44CC6Kej56CB5Zmo
//5ouS57ud5YyF5ZCrIEJhc2U2NCDlrZfmr43ooajku6XlpJblrZfnrKbnmoTmlbDmja7jgII=

// 解码
Base64.Decoder decoder = Base64.getMimeDecoder();
byte[] decoderResult = decoder.decode(encoderResult);
System.out.println("解码结果:" + new String(decoderResult));
//解码结果:使用 RFC 4648 表 2 中指定的 “URL 和文件名安全 Base64 字母表” 进行编码和解码。编码器不添加任何换行(行分隔符)字符。解码器拒绝包含 Base64 字母表以外字符的数据。
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号