injava什么是Base64编码?在回答这个问题之前,我们需要先了解一下计算机中文件的分类。对于计算机来说,文件可以分为两类,一类是文本文件,一类是二进制文件。对于二进制文件,它的内容是用二进制表示的,人类不能立即理解。如果您尝试使用文本编辑器打开二进制文件,您可能会看到乱码。这是因为二进制文件的编码方式不同于文本文件,所以当文本编辑器试图将二进制文件翻译成文本内容时,就会出现乱码。对于文本文件,也有很多编码方式,比如最早的ASCII编码和目前常用的UTF-8、UTF-16等编码方式。即使是文本文件,如果您使用不同的编码打开它,您也可能会看到乱码。所以无论是文本文件还是二进制文件,都需要统一编码格式。也就是说,写的代码长什么样,那么数据读出的代码也应该与之匹配。Base64编码实际上是一种将二进制数据编码成可视化ASCII字符的编码方法。为什么会有这样的要求?我们知道计算机世界的发展不是一蹴而就的,它是一个缓慢增长的过程,对于字符编码,最早只支持ASCII编码,后来扩展到Unicode等等。那么对于很多应用来说,不支持ASCII编码以外的编码格式,那么在这些系统中如何显示非ASCII码呢?解决方法是进行编码映射,将非ASCII字符映射为ASCII字符。而base64就是这样一种编码方式。使用Base64的常见位置是在网页中。有时候我们需要在网页中展示图片,那么我们可以将图片进行base64编码,填充到html中。另一种应用是将文件进行base64编码,作为邮件附件发送。JAVA对base64的支持既然base64编码这么好用,那我们就来看看JAVA中base64的实现。java中有对应的base64实现,叫做java.util.Base64。这个类是Base64的一个工具类,是JDK在1.8版本引入的。Base64提供了三个getEncoder和getDecoder方法。通过获取对应的Encoder和Decoder,然后可以调用Encoder的encode和decode方法对数据进行编解码,非常方便。先来看下Base64的基本使用示例://使用encoder对String进行编码encodedString=Base64.getEncoder().encodeToString("whatisyournamebaby?".getBytes("utf-8"));System.out.println("Base64编码字符串:"+encodedString);//使用编码器解码byte[]decodedBytes=Base64.getDecoder().decode(encodedString);System.out.println("解码后的字符串:"+newString(decodedBytes,"utf-8"));作为工具类,JDK中提供的Base64工具类还是很有用的。我不会在这里详细解释它的使用。本文主要分析Base64在JDK中是如何实现的。JDK中Base64的分类与实现JDK中的Base64类提供了三种编码器方法,分别是getEncoder、getUrlEncoder和getMimeEncoder:publicstaticEncodergetEncoder(){returnEncoder.RFC4648;}publicstaticEncodergetUrlEncoder(){返回编码器。RFC4648_URLSAFE;}publicstaticEncodergetMimeEncoder(){returnEncoder.RFC2045;同样,它也提供了三个对应的解码器,分别是getDecoder、getUrlDecoder、getMimeDecoder:publicstaticDecodergetDecoder(){returnDecoder.RFC4648;}publicstaticDecodergetUrlDecoder(){returnDecoder.RFC4648_URLSAFE;}publicstaticDecodergetMimeDecoder(){returnDecoder.RFC2045;从代码中可以看出,这三种编码分别对应RFC4648、RFC4648_URLSAFE和RFC2045。这三个是base64编码的变体。让我们看看它们之间的区别:编码名称编码字符编码字符编码字符62nd63rdCompletioncharacterRFC2045:Base64transferencodingforMIME+/=mandatoryRFC4648:base64(standard)+/=optionalRFC4648:base64url(URL-andfilename-safestandard)-_=optional可以看到base64和Base64url的区别是第62位和63位的编码字符不同,而base64forMIME和base64的区别是是否强制补全。此外,对于Basic和base64url,不会添加行分隔符,而base64forMIME会在一行超过76个字符后添加'\r'和'\n'作为行分隔符。最后,如果在解码过程中,发现有字符没有存储在Base64映射表中,处理不当,base64和Base64url会直接拒绝,而base64forMIME会忽略。base64和Base64url的区别可以通过下面两个方法看出:privatestaticfinalchar[]toBase64={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'};privatestaticfinalchar[]toBase64URL={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_'};而对于MIME来说,它定义了一行中的最大字符数和换行符:privatestaticfinalintMIMELINEMAX=76;privatestaticfinalbyte[]CRLF=newbyte[]{'\r','\n'};Base64的高级用法一般情况下,经过Base64编码后的对象长度是固定的,我们只需要将输入的对象转换为字节数组即可调用encode或decode方法。但在某些情况下我们需要对流数据进行转换。这时候我们可以使用Base64提供的两种对Stream进行包装的方法:publicOutputStreamwrap(OutputStreamos)返回新的EncOutputStream(os,isURL?toBase64URL:toBase64,newline,linemax,doPadding);}publicInputStreamwrap(InputStreamis){Objects.requireNonNull(is);returnnewDecInputStream(is,isURL?fromBase64URL:fromBase64,isMIME);这两个方法分别对应encoder和decoder。综上所述,以上就是JDK中Base64的实现和使用。虽然base64有很多变种,但JDK中的Base64只实现了使用最广泛的三种。大家在使用的时候一定要区分Base64的具体实现,以免出现问题。本文已收录于http://www.flydean.com/14-1-1-java-base64/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!
