• Java技术 | 细谈 Java 8 中的 Base64


    简要了解

    Base 64是一种使64个字符来表示任意二进制数据的方法。Base 64是一种非常常用的二进制编解码方案。

    有些说法是说,使用Base 64作为加密解密的功能,比如一个Web系统中,密码字段存入数据库的时候使用Base64.encode一下,其实Base 64的编码、解码方法都是简单公开的,用以加密、解密实在谈不上啥保障性。

    在Java 8中,整合了Base 64。Java 8 为开发者提供了 java.util.Base64 的工具类,Java 8现在有内置编码器和解码器的Base 64编码。在Java 8中有三种类型的Base 64编码。

    第一种,简单Base 64

    Basic 编码是标准的Base 64编码,用于处理常规的需求:输出的内容不添加换行符,而且输出的内容由64个基本字符组成。

    输出映射设置字符在A-ZA-Z0-9+/。编码器不添加任何换行输出和解码器拒绝在A-Za-z0-9+/以外的任何字符。

    第二种,URL编码

    输出映射设置字符在A-Za-z0-9-_。输出URL和文件名安全。由于标准的Basic编码可能会出现+ / ,在URL中就不能直接作为参数,所以又有一种“url safe” 的Base 64编码,其实就是吧字符 +/分别变成-_在这里插入图片描述

    第三种,MIME编码

    输出映射到MIME友好的格式。输出表示在每次不超过76个字符行和使用' '后跟一个换行符' '回车作为行分隔符。无行隔板的存在是为了使编码的结束输出。MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用对应的应用程序来打开的方式类型。

    它是一种互联网标准,扩展了电子邮件标准,使其可以支持:非ASCII字符文本;非文本格式附件(二进制、声音、图像等);由多部分组成的消息体;包含非ASCII字符的头信息等。

    举个栗子:右键中有一个Word附件(二进制文件),点击预览,浏览器会直接打开Office。可以理解为MIME设定了这种对应关系。

    MIME编码器会使用基本的字母数字产生Base 64输出,而且对MIME格式友好:每一行输出不超过76个字符,而且每行以“ ”符结束。

    实用API与代码示例

    API

    Base 64类

    序号 方法 描述
    1 Base64.getEncoder() 返回一个 Base64.Encoder ,编码使用基本型 base64 编码方案
    2 Base64.getDecoder() 返回一个 Base64.Decoder ,解码使用基本型 base64 编码方案
    3 Base64. getUrlEncoder() 返回一个 Base64.Encoder ,编码使用 URL 和文件名安全型 base64 编码方案
    4 Base64.getUrlDecoder() 返回一个 Base64.Decoder ,解码使用 URL 和文件名安全型 base64 编码方案。
    5 Base64.getMimeEncoder() 返回一个 Base64.Encoder ,编码使用 MIME 型 base64 编码方案。
    6 Base64.getMimeEncoder(int lineLength, byte[] lineSeparator) 返回一个 Base64.Encoder ,编码使用 MIME 型 base64 编码方案,可以通过参数指定每行的长度及行的分隔符。
    7 Base64.getMimeDecoder() 返回一个 Base64.Decoder ,解码使用 MIME 型 base64 编码方案。

    内嵌类Encoder

    序号 方法名 描述
    1 byte[] encode(byte[] src) 编码,返回一个byte数组
    2 int encode(byte[] src, byte[] dst) 编码,写进新的byte数组
    3 String encodeToString(byte[] src) 编码,返回一个字符串
    4 ByteBuffer encode(ByteBuffer buffer) 编码
    5 OutputStream wrap(OutputStream os) 编码
    6 Encoder withoutPadding() 编码

    内嵌类Decoder

    序号 方法名 描述
    1 byte[] decode(byte[] src) 解码,返回一个byte数组,入参为byte数组
    2 byte[] decode(String src) 解码,返回一个byte数组,入参为字符串
    3 int decode(byte[] src, byte[] dst) 解码
    4 ByteBuffer decode(ByteBuffer buffer) 解码
    5 InputStream wrap(InputStream is) 解码

    代码示例

    package com.kjgym.common.java8;
    
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    
    /**
     * @author kjgym
     * @description Demo for Java8's Base64
     * @date 2019/9/17 11:25
     */
    public class Java8Base642 {
    
        public static void main(String[] args) {
            final String demoStr = "kjgym";
            final byte[] strByte = demoStr.getBytes(StandardCharsets.UTF_8);
    
            // 基本型编码方案
            String s = Base64.getEncoder().encodeToString(strByte);
            System.out.println("基本编码: " + s);
            String ss = new String(Base64.getDecoder().decode(s));
            System.out.println("解码: " + ss);
    
            // 使用 URL 和文件名安全型 base64 编码方案。
            String s1 = Base64.getEncoder().encodeToString(strByte);
            System.out.println("URL编码: " + s1);
            String ss1 = new String(Base64.getUrlDecoder().decode(s));
            System.out.println("解码: " + ss1);
    
            // 使用 MIME 型 base64 编码方案
            String s2 = Base64.getMimeEncoder().encodeToString(strByte);
            System.out.println("MIME编码: " + s2);
            String ss2 = new String(Base64.getMimeDecoder().decode(s));
            System.out.println("解码: " + ss2);
    
        }
    }
    

    结果:

    基本编码: a2pneW0= 解码: kjgym URL编码: a2pneW0= 解码: kjgym MIME编码: a2pneW0= 解码: kjgym

    阅读源码

    1. 先来总体看一下Base 类,该类主要包含两个内嵌类EncoderDecoder以及七个构造内嵌类的方法:

    在这里插入图片描述

    1. 再看两个内嵌类。比如Encoder(部分源代码):

      public static class Encoder {
      
              private final byte[] newline;
              private final int linemax;
              private final boolean isURL;
              private final boolean doPadding;
      
              private Encoder(boolean isURL, byte[] newline, int linemax, boolean doPadding {
                  this.isURL = isURL;
                  this.newline = newline;
                  this.linemax = linemax;
                  this.doPadding = doPadding;
              }
      
              static final Encoder RFC4648 = new Encoder(false, null, -1, true);
              static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1, true);
              static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true);
      
              public byte[] encode(byte[] src) {}
      
              public int encode(byte[] src, byte[] dst) {}
      
              @SuppressWarnings("deprecation")
              public String encodeToString(byte[] src) {}
      
              public ByteBuffer encode(ByteBuffer buffer) {}
      
              public OutputStream wrap(OutputStream os) {}
      
              public Encoder withoutPadding() {}
      
              private int encode0(byte[] src, int off, int end, byte[] dst) {}
          }
      

      构造器私有化,对外提供单个静态对象,然后在Base 64类中,使用getEncoder的方式爱调用,使用了单例模式。

      static final Encoder RFC4648 = new Encoder(false, null, -1, true);
      static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1, true);
      static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true);
      
    2. Decoder与上文Encoder相似,这里不再赘述。有兴趣自己Ctrl + 单击去看源码。

    拓展

    1. StandardCharsets类。在java.nio.charset包下的一个类,在字符串和byte数组相互转换需要制定编码的时候使用。该类有六种编码格式:

      /*
       * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
       * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
       */
      package java.nio.charset;
      
      /**
       * Constant definitions for the standard {@link Charset Charsets}. These
       * charsets are guaranteed to be available on every implementation of the Java
       * platform.
       *
       * @see <a href="Charset#standard">Standard Charsets</a>
       * @since 1.7
       */
      public final class StandardCharsets {
      
          private StandardCharsets() {
              throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!");
          }
          /**
           * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
           * Unicode character set
           */
          public static final Charset US_ASCII = Charset.forName("US-ASCII");
          /**
           * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
           */
          public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
          /**
           * Eight-bit UCS Transformation Format
           */
          public static final Charset UTF_8 = Charset.forName("UTF-8");
          /**
           * Sixteen-bit UCS Transformation Format, big-endian byte order
           */
          public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
          /**
           * Sixteen-bit UCS Transformation Format, little-endian byte order
           */
          public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
          /**
           * Sixteen-bit UCS Transformation Format, byte order identified by an
           * optional byte-order mark
           */
          public static final Charset UTF_16 = Charset.forName("UTF-16");
      }
      
      
  • 相关阅读:
    Java面试题
    verilog之锁存器和触发器
    verilog基本语法之always和assign
    verilog之基本结构
    ZYNQ7000系列学习之TF卡读写实验
    英语文档阅读学习系列之ZYNQ-7000 All Programmable SOC Packaging and Pinout
    物理之纳电子
    英语文档阅读学习系列之Zynq-7000 EPP Software Developers Guide
    嵌入式C语言设计学习
    ZYNQ7000系列学习之自定义模块构成IP
  • 原文地址:https://www.cnblogs.com/kjgym/p/11578023.html
Copyright © 2020-2023  润新知