Base64编码介绍及基于Java语言实现

简介: Base64编码介绍及基于Java语言实现

Base64编码介绍及基于Java语言实现



Base64编码被设计用来表示任意顺序的八位一个字节单元,允许使用大写和小写字符而不要求内容可读。65个US-ASCII子集被用来表示Base64编码,所以每六位表示一个可以打印的Base64的字符,第65字符’=’被用来表示特殊处理的功能字符,后面会详细说明。



预编码处理一次输入24位(三个字符)作为一组,输出的是四个Base64的编码字符24位(每个字符六位)。编码处理遵循从左到右的顺序,一个24位的输入可以看作是三个八位的字符组,


编码以后,24位的字符则被转换为四个6位的字符组,每个字符被翻译成Base64字符表中的匹配的一个字符。



每六位都被转换成为一个index数值去匹配Base64编码表中的一个字符输出,Base64的字符表如下:



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





字符’=’作为填充字符,对于任何不满足24为输入的编码字符,以零做作为填充成为24位(三字节)输入,对于任何输出的编码字符小于24位的都应当以’=’字符填充。对于以下情形:



Ø        最后输入正好是24位的编码字符,则不需要’=’字符填充,输出即为四个Base64字符编码.


Ø        最后输入只有八位的编码字符,则需要填充两个特殊字符’=’,输出即为两个Base64字符编码加上两个’=’.


Ø        最后输入只有十六位的编码字符,则需要填充一个特殊字符’=’,输出即为三个Base64字符加上一个’=’.


 


把一个二进制的数据转换为Base64的编码,下面的例子就说明Base64怎么编码三个字节的二进制数据的。


+--first octet--+-second octet--+--third octet--+


|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|


+-----------+---+-------+-------+---+-----------+


|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|


+--1.index--+--2.index--+--3.index--+--4.index--+



许多网络程序中用来传输二进制文件也经常采用Base64的编码算法,一个最典型的例子就是Email的应用协议SMPT发送MIME数据的时候就常采用Base64来发送,而且已经被写入标准的RFC中,在Java语言中,JDK已经提供了Base64的API。



下面基于Java实现的Base64的编码和解码程序,相比于JDK6中把Base64编码和解码分在两个不同的API Class中,因此还把许多人搞得很晕来说,也许本人的实现会略微方便点。

package com.gloomyfish.smtp.util;
 
 
public class Base64Coder {
  
  public final static char[] base64_alphabet = new char[]{
            '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','+','/','='
  };
  
  public static String encode(String content) {
    
    byte[] data = content.getBytes();
    int length = data.length;
    byte[] char_array_3 = new byte[]{0, 0, 0};
    byte[] char_array_4 = new byte[]{'=','=','=','='};
    String retContent = "";
    int i = 0;
    int j = 0;
    int reversePos = 0;
    while(length > 0) {
      length--;
      char_array_3[i++] = data[reversePos++];
      if(i==3) {
        char_array_4[0] = (byte)((char_array_3[0] & 0xfc) >> 2); // convert the char
          char_array_4[1] = (byte)(((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4));
          char_array_4[2] = (byte)(((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6));
          char_array_4[3] = (byte)(char_array_3[2] & 0x3f);
          for(i = 0; (i <4) ; i++)
            retContent += base64_alphabet[char_array_4[i]];
          i = 0;
      }
    }
    
    // handling the last input content
      if (i > 0 )
      {
        for(j = i; j < 3; j++)
          char_array_3[j] = 0; // padding of zero
 
        char_array_4[0] = (byte)((char_array_3[0] & 0xfc) >> 2); // right shift
        char_array_4[1] = (byte)(((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4));
        char_array_4[2] = (byte)(((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6));
        char_array_4[3] = (byte)(char_array_3[2] & 0x3f);
 
        for (j = 0; (j < i + 1); j++)
          retContent += base64_alphabet[char_array_4[j]];
 
        while((i++ < 3)) // padding of '=' of output string
          retContent += '=';
 
      }
    return retContent;
  }
  
  public static String decode(String enContent) {
    byte[] data = enContent.getBytes();
    int i = 0, j = 0, enCode = 0;
    int mLength = data.length;
    byte[] char_array_4 = new byte[4];
    byte[] char_array_3 = new byte[3];
    String retContent = "";
 
    // filter out the padding '=' chars
      while (mLength > 0 && (((char)data[enCode]) != '=') && isBase64((char)data[enCode])) 
      {
        mLength--;
        char_array_4[i++] = data[enCode++];
        if (i ==4) {
          for (i = 0; i <4; i++)
            char_array_4[i] = findChar((char)char_array_4[i]);
 
          char_array_3[0] = (byte)((char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4));
          char_array_3[1] = (byte)(((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2));
          char_array_3[2] = (byte)(((char_array_4[2] & 0x3) << 6) + char_array_4[3]);
 
          for (i = 0; (i < 3); i++)
            retContent += (char)char_array_3[i];
          i = 0;
        }
      }
 
      // last content handling
      if (i > 0) 
      {
        for (j = i; j <4; j++)
          char_array_4[j] = 0;
 
        for (j = 0; j <4; j++)
          char_array_4[j] = findChar((char)char_array_4[j]);
 
        char_array_3[0] = (byte)((char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4));
        char_array_3[1] = (byte)(((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2));
        char_array_3[2] = (byte)(((char_array_4[2] & 0x3) << 6) + char_array_4[3]);
 
        for (j = 0; (j < i - 1); j++) 
          retContent += (char)char_array_3[j];
      }
 
      return retContent;
  }
  
  public static boolean isBase64(char c) 
  {
    boolean base64 = false;
    for(int i=0; i<64; i++) {
      if( c == base64_alphabet[i]) {
        base64 = true;
        break;
      }
    }
    return base64;
  }
  
  public static byte findChar(char x) {
    byte index = 64; // 65th char '='
    for(int i=0; i<64; i++) {
      if( x == base64_alphabet[i]) {
        index = (byte)i;
        break;
      }
    }
    return index;
  }
  
  /**
   * <p> test data and result should like below output , RFC4648 Sample </p>
   *  BASE64("") = ""
   *  BASE64("f") = "Zg=="
   *  BASE64("fo") = "Zm8="
   *  BASE64("foo") = "Zm9v"
   *  BASE64("foob") = "Zm9vYg=="
   *  BASE64("fooba") = "Zm9vYmE="
   *  BASE64("foobar") = "Zm9vYmFy"
   *
   *
   * @param args
   */
  public static void main(String[] args) {
    // BASE64Encoder coder = new BASE64Encoder();
    // System.out.println(coder.encode("foobar".getBytes()));
    
    System.out.println("#--------------encode---------------#");
    System.out.println(encode(""));
    System.out.println(encode("f"));
    System.out.println(encode("fo"));
    System.out.println(encode("foo"));
    System.out.println(encode("foob"));
    System.out.println(encode("fooba"));
    System.out.println(encode("foobar"));
    System.out.println(encode("123456789sS{1}quot;));
    System.out.println("#--------------decode---------------#");
    System.out.println(decode(""));
    System.out.println(decode("Zg=="));
    System.out.println(decode("Zm8="));
    System.out.println(decode("Zm9v"));
    System.out.println(decode("Zm9vYg=="));
    System.out.println(decode("Zm9vYmE="));
    System.out.println(decode("Zm9vYmFy"));
    System.out.println(decode("MTIzNDU2Nzg5c1Mk"));
    
  }
}
目录
打赏
0
0
0
0
81
分享
相关文章
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
47 5
Java中将图片转换为base64格式的技巧
这样,你就可以在Java中将图片转换为Base64格式了。这个方法的实现非常简单,只需要使用Java的内置库,无需任何额外的库。希望这个方法对你有所帮助。
52 22
Java语言位运算符详解
Java语言提供了7种位运算符:按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(&lt;&lt;)、带符号右移(&gt;&gt;)和无符号右移(&gt;&gt;&gt;)。这些运算符主要用于对long、int、short、byte和char类型的数据进行二进制位级别的操作,不能用于double、float和boolean类型。文中详细讲解了每种运算符的规则和应用场景,并指出位运算在实际开发中有重要应用价值,不仅限于面试。
145 2
|
2月前
|
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
260 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
420 5
课时2:Java语言特点
课时2介绍了Java语言的多个关键特性。作为开源且半开源的产品,Java成为通用技术标准,拥有透明的开发环境。其面向对象的设计、自动内存回收、简化指针处理(使用引用)、支持多线程编程、高效的网络处理能力(如NIO)及良好的可移植性,共同促成了Java的强大生态系统和广泛应用。
Java语言------图书馆管理系统(入门简略版)
Java语言------图书馆管理系统(入门简略版)
173 0
Java语言------图书馆管理系统(入门简略版)
【Java编程进阶】Java语言基础入门篇
整个Java全栈编程知识体系十分庞大,包括JavaSE知识,Web前端,Web后端,数据库相关的知识等,初学者应该系统踏实的学习,一步一个脚印。Java语言是一种完全面向对象的跨平台语言。有很多突出的优点,例如简单易学,面向对象,分布式,安全可靠,解释型语言,跨平台运行,可移植高性能多线程,可实现网络编程等。
242 0
【Java编程进阶】Java语言基础入门篇
Java学习路线-53:EL(表达式语言)入门及 EL 函数库
Java学习路线-53:EL(表达式语言)入门及 EL 函数库
139 0
下一篇
oss创建bucket