推荐:Base64在线编码、解码
一、Java8 base64来源简介
Java 8将主要用于引入lambdas、streams、新的日期/时间模型,以及将Nashorn JavaScript引擎引入到Java 中。有些人还会记得Java 8引入各种小而有用的功能,好比Base64 API。什么是Base64,我如何使用这个API?这篇文章回答了这些题目。
二、什么是Base64?
Base64是一种二进制到文本编码方案,通过将二进制数据转换为基数-64表示,以可打印的ASCII字符串格式表示二进制数据。每个Base64数字代表正好6位的二进制数据。Base64用于防止数据在通过信息系统(如电子邮件)传输时被修改,而这些信息系统可能不是8位清理(它们可能包含8位值)。例如,您将图像附加到电子邮件消息,并希望图像到达另一端而不会出现乱码。您的电子邮件软件Base64对图像进行编码并将等效文本插入到邮件中,如下所示:
Content-Disposition: inline;
filename=IMG_0006.JPG
Content-Transfer-Encoding: base64
/9j/4R/+RXhpZgAATU0AKgAAAAgACgEPAAIAAAAGAAAAhgEQAAIAAAAKAAAAjAESAAMAAAABAAYA
AAEaAAUAAAABAAAAlgEbAAUAAAABAAAAngEoAAMAAAABAAIAAAExAAIAAAAHAAAApgEyAAIAAAAU
AAAArgITAAMAAAABAAEAAIdpAAQAAAABAAAAwgAABCRBcHBsZQBpUGhvbmUgNnMAAAAASAAAAAEA
...
NOMbnDUk2bGh26x2yiJcsoBIrvtPe3muBbTRGMdeufmH+Nct4chUXpwSPk/qK9GtJRMWWVFbZ0JH
I4rf2dkZSbOjt7hhEzwcujA4I7Gust75pYVwAPpXn+kzNLOVYD7xFegWEKPkHsM/pU1F0NKbNS32
o24sSCOlaaFYLUhjky4x9PSsKL5bJsdWkAz3xirH2dZLy1DM2C44zx1FZqL2PTXY/9k=
该图显示该编码图像以其开头/和结尾=。在...表明我还没有为简洁的文字。请注意,此示例或任何其他示例的整个编码比原始二进制数据大约33%。
收件人的电子邮件软件将Base64解码编码的文本图像,以恢复原始的二进制图像。对于此示例,图像将与消息的其余部分一起显示。
三、Base64编码和解码
Base64依赖于简单的编码和解码算法。它们使用65个字符的US-ASCII子集,其中前64个字符中的每一个映射到等效的6位二进制序列。这是字母表:Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y 第65个字符(=)用于将Base64编码的文本填充为整数大小,就像刚才解释的那样.
编码算法接收8位字节的输入流。假定这个流首先排序为最高位:第一位是第一个字节中的高位,第八位是这个字节中的低位,依此类推。
从左到右,这些字节被组织成24位组。每组被视为四个连接的6位组。每个6位组索引为64个可打印字符的数组; 输出结果字符。
当正在编码的数据的末尾有少于24位可用时,零位被添加(在右边)以形成整数个6位组。然后,=可以输出一个或两个填充字符。有两种情况需要考虑:
- 剩余的一个字节:将四个零位附加到该字节以形成两个6位组。每个组索引数组并输出结果字符。在这两个字符之后,
=输出两个填充字符。 - 剩下的两个字节:将两个零位附加到第二个字节以形成三个6位组。每个组索引数组并输出结果字符。在这三个字符之后,
=输出一个填充字符。
让我们考虑三个示例来了解编码算法的工作原理。首先,假设我们希望编码
@!*:
Source ASCII bit sequences with prepended 0 bits to form 8-bit bytes:
@ ! *
01000000 00100001 00101010
Dividing this 24-bit group into four 6-bit groups yields the following:
010000 | 000010 | 000100 | 101010
These bit patterns equate to the following indexes:
16 2 4 42
Indexing into the Base64 alphabet shown earlier yields the following encoding:
QCEq 我们将继续缩短输入序列以@!:
Source ASCII bit sequences with prepended 0 bits to form 8-bit bytes:
@ !
01000000 00100001
Two zero bits are appended to make three 6-bit groups:
010000 | 000010 | 000100
These bit patterns equate to the following indexes:
16 2 4
Indexing into the Base64 alphabet shown earlier yields the following encoding:
QCE
An = pad character is output, yielding the following final encoding:
QCE= 最后一个例子将输入序列缩短为@:
Source ASCII bit sequence with prepended 0 bits to form 8-bit byte:
@
01000000
Four zero bits are appended to make two 6-bit groups:
010000 | 000000
These bit patterns equate to the following indexes:
16 0
Indexing into the Base64 alphabet shown earlier yields the following encoding:
QA
Two = pad characters are output, yielding the following final encoding:
QA== 解码算法是编码算法的逆向算法。但是,在检测到不在Base64字母表中的字符或填充字符的数量不正确时,可以自由采取适当的措施。四、Base64变体
已经设计了几个Base64变体。某些变体要求将编码的输出流分成多行固定长度,每行不超过一定的长度限制,并且(最后一行除外)通过行分隔符与下一行分隔开(回车\r后跟一个换行符\n)。我描述了Java 8的Base64 API支持的三种变体。查看Wikipedia的Base64条目以获取完整的变体列表。
基本
RFC 4648描述了称为Basic的Base64变体。此变体使用RFC 4648和RFC 2045的表1中所示的Base64字母表(并在本文前面显示)进行编码和解码。编码器将编码的输出流视为一行; 没有行分隔符输出。解码器拒绝包含Base64字母以外的字符的编码。请注意,可以覆盖这些和其他规定。
哑剧
RFC 2045描述了一种称为MIME的Base64变体。该变体使用RFC 2045表1中提供的Base64字母表进行编码和解码。编码输出流被组织成不超过76个字符的行; 每行(除最后一行)通过行分隔符与下一行分隔开。在解码期间,所有行分隔符或Base64字母表中未找到的其他字符都将被忽略。
URL和文件名安全
RFC 4648描述了称为URL和文件名安全的Base64变体。该变体使用RFC 4648表2中提供的Base64字母表进行编码和解码。字母与前面显示的字母相同,只是-替换+和_替换/。不输出行分隔符。解码器拒绝包含Base64字母以外的字符的编码。
Base64编码在冗长的二进制数据和HTTP GET请求的上下文中很有用。这个想法是编码这些数据,然后将其附加到HTTP GET URL。如果使用Basic或MIME变体,则编码数据中的任何+或/字符必须按照十六进制序列进行URL编码(+变为%2B并/变为%2F)。生成的URL字符串会稍微长一些。通过更换+同-和/同_,URL和文件名安全消除了对URL编码器/解码器(和它们的编码值的长度影响)的需要。另外,由于Unix和Windows文件名不能包含,因此当编码数据用于文件名时,此变体很有用/。
五、使用Java的Base64 API
爪哇8引入一个Base64 API由所述的java.util.Base64类及其沿Encoder和Decoder嵌套static类。Base64介绍了几种static获取编码器和解码器的方法:
Base64.Encoder getEncoder():返回Basic变体的编码器。Base64.Decoder getDecoder():返回Basic变体的解码器。Base64.Encoder getMimeEncoder():返回MIME变体的编码器。Base64.Encoder getMimeEncoder(int lineLength, byte[] lineSeparator):返回编码器,修改后的MIME变体lineLength(给出四舍五入到最接近的4的倍数 - 输出在lineLength<= 0 时不会分隔成行)和lineSeparator。它包含RFC 2045表1中提供的任何Base64字母字符java.lang.IllegalArgumentException时抛出lineSeparator。RFC 2045的编码器,这是从noargument
getMimeEncoder()方法返回,是相当严格的。例如,该编码器创建76个字符的固定行长度(最后一行除外)的编码文本。如果你想要一个编码器来支持RFC 1421,它表示一个64字符的固定行长度,你需要使用getMimeEncoder(int lineLength, byte[] lineSeparator)。Base64.Decoder getMimeDecoder():返回MIME变体的解码器。Base64.Encoder getUrlEncoder():返回URL和Filename Safe变体的编码器。Base64.Decoder getUrlDecoder():返回URL和Filename Safe变体的解码器。
Base64.Encoder介绍了几种用于编码字节序列的线程安全实例方法。将空引用传递给以下方法之一会导致java.lang.NullPointerException:
byte[] encode(byte[] src):将所有字节编码src到新分配的字节数组中,此方法返回。int encode(byte[] src, byte[] dst):将所有字节编码src到dst(从偏移量0开始)。如果dst不足以保存编码,IllegalArgumentException则抛出。否则,dst返回写入的字节数。ByteBuffer encode(ByteBuffer buffer):将所有剩余的字节编码buffer到新分配的java.nio.ByteBuffer对象中。返回后,buffer其职位将更新到极限; 其限制不会改变。返回的输出缓冲区的位置将为零,其限制将为结果编码字节的数量。String encodeToString(byte[] src):将所有字节编码src为返回的字符串。调用此方法等同于执行new String(encode(src), StandardCharsets.ISO_8859_1)。Base64.Encoder withoutPadding():返回与此编码器等效编码的编码器,但不在编码字节数据的末尾添加任何填充字符。OutputStream wrap(OutputStream os):包装输出流以编码字节数据。建议在使用后及时关闭返回的输出流,在此期间,它会将所有可能的剩余字节清除到基础输出流。关闭返回的输出流将关闭基础输出流。
Base64.Decoder提出了几种解码字节序列的线程安全实例方法。将空引用传递给以下方法之一会导致NullPointerException:
https://www.leftso.com/article/449.html