栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

手写Java版Base64算法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

手写Java版Base64算法

base64概述

base64就是选出64个字符:a-z、A-Z、0-9、+、/(再加上作为垫字的"=",实际上是65个字符),作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。

转换方式可以分为四步:

  • 第一步,将每三个字节作为一组,一共是24个二进制位。
  • 第二步,将这24个二进制位分为四组,每个组有6个二进制位。
  • 第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。
  • 第四步,根据下表,得到扩展后的每个字节的对应符号,这就是base64的编码值。
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   
15 P  32 g   49 x
16 Q  33 h   50 y

因为base64将三个字节转化成四个字节,因此base64编码后的文本,会比原文本大出三分之一左右。

示例

单词Man转成base64编码:

  • 第一步,“M”、“a”、"n"的ASCII值分别是77、97、110,对应的二进制值是01001101、01100001、01101110,将它们连成一个24位的二进制字符串010011010110000101101110。
  • 第二步,将这个24位的二进制字符串分成4组,每组6个二进制位:010011、010110、000101、101110。
  • 第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节:00010011、00010110、00000101、00101110。它们的十进制值分别是19、22、5、46。
  • 第四步,根据上表,得到每个值对应base64编码,即T、W、F、u。
字节数不足三 二个字节

二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的base64编码,再在末尾补上一个"="号。

一个字节

一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的base64编码,再在末尾补上两个"="号。

Java实现
public class Mybase64 {

  private static final char[] CHS = {
      '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', '+', '/'};

  private static final Map CHS_MAP = new HashMap<>(64);

  static {
    for (int i = 0; i < CHS.length; i++) {
      CHS_MAP.put((byte) CHS[i], (byte) i);
    }
  }

  public static byte[] encode(byte[] bytes) {

    int groupCount = bytes.length / 3;
    int remainCount = bytes.length % 3;

    int encLength;
    if (remainCount == 0) {
      encLength = groupCount * 4;
    } else {
      encLength = (groupCount + 1) * 4;
    }

    int index, encI;
    byte b1, b2, b3;

    byte[] encBuf = new byte[encLength];

    for (int i = 0; i < groupCount; i++) {
      index = i * 3;

      b1 = bytes[index];
      b2 = bytes[index + 1];
      b3 = bytes[index + 2];

      encI = i * 4;
      encBuf[encI] = (byte) CHS[(b1 >> 2) & 0x3F];
      encBuf[encI + 1] = (byte) CHS[((b1 << 4) & 0x30) | ((b2 >> 4) & 0x0F)];
      encBuf[encI + 2] = (byte) CHS[((b2 << 2) & 0x3C) | ((b3 >> 6) & 0x03)];
      encBuf[encI + 3] = (byte) CHS[b3 & 0x3F];
    }

    if (remainCount == 2) {
      index = groupCount * 3;
      b1 = bytes[index];
      b2 = bytes[index + 1];
      b3 = 0;

      encI = groupCount * 4;
      encBuf[encI] = (byte) CHS[(b1 >> 2) & 0x3F];
      encBuf[encI + 1] = (byte) CHS[((b1 << 4) & 0x30) | ((b2 >> 4) & 0x0F)];
      encBuf[encI + 2] = (byte) CHS[((b2 << 2) & 0x3C) | ((b3 >> 6) & 0x03)];
      encBuf[encI + 3] = '=';
    }

    if (remainCount == 1) {
      index = groupCount * 3;
      b1 = bytes[index];
      b2 = 0;

      encI = groupCount * 4;
      encBuf[encI] = (byte) CHS[(b1 >> 2) & 0x3F];
      encBuf[encI + 1] = (byte) CHS[((b1 << 4) & 0x30) | ((b2 >> 4) & 0x0F)];
      encBuf[encI + 2] = encBuf[encI + 3] = '=';
    }

    return encBuf;
  }

  public static byte[] decode(byte[] encBytes) {

    int encLen = encBytes.length;
    int groupCount = encLen / 4;

    int decLen;
    int remainCount;
    if (encBytes[encLen - 1] == '=') {
      if (encBytes[encLen - 2] == '=') {
        decLen = groupCount * 3 - 2;
        remainCount = 1;
      } else {
        decLen = groupCount * 3 - 1;
        remainCount = 2;
      }
    } else {
      decLen = groupCount * 3;
      remainCount = 0;
    }

    int index, index2;
    byte[] decBytes = new byte[decLen];
    byte b1, b2, b3;

    for (int i = 0; i < groupCount - 1; i++) {
      decodeGroup(encBytes, decBytes, i);
    }

    if (remainCount == 2) {
      index = (groupCount - 1) * 4;
      b1 = CHS_MAP.get(encBytes[index]);
      b2 = CHS_MAP.get(encBytes[index + 1]);
      b3 = CHS_MAP.get(encBytes[index + 2]);

      index2 = (groupCount - 1) * 3;
      decBytes[index2] = (byte) (((b1 << 2) & 0xFF) | ((b2 >> 4) & 0xFF));
      decBytes[index2 + 1] = (byte) (((b2 << 4) & 0xFF) | ((b3 >> 2) & 0xFF));
    }

    if (remainCount == 1) {
      index = (groupCount - 1) * 4;
      b1 = CHS_MAP.get(encBytes[index]);
      b2 = CHS_MAP.get(encBytes[index + 1]);
      index2 = (groupCount - 1) * 3;
      decBytes[index2] = (byte) (((b1 << 2) & 0xFF) | ((b2 >> 4) & 0xFF));
    }

    if (remainCount == 0) {
      decodeGroup(encBytes, decBytes, groupCount - 1);
    }

    return decBytes;
  }

  private static void decodeGroup(byte[] encBytes, byte[] decBytes, int i) {
    byte b1, b2, b3, b4;

    int index = i * 4;

    b1 = CHS_MAP.get(encBytes[index]);
    b2 = CHS_MAP.get(encBytes[index + 1]);
    b3 = CHS_MAP.get(encBytes[index + 2]);
    b4 = CHS_MAP.get(encBytes[index + 3]);

    int index2 = i * 3;
    decBytes[index2] = (byte) (((b1 << 2) & 0xFF) | ((b2 >> 4) & 0xFF));
    decBytes[index2 + 1] = (byte) (((b2 << 4) & 0xFF) | ((b3 >> 2) & 0xFF));
    decBytes[index2 + 2] = (byte) (((b3 << 6) & 0xFF) | (b4 & 0xFF));
  }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/390348.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号