`
mycream
  • 浏览: 54166 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

BASE64 编码实现

    博客分类:
  • JAVA
阅读更多
用了几天的时间实现了BASE64编码,编程能力还有待提高啊

下面就描述下我的实现过程吧。

首先,当然要知道BASE64的编码规则了,至于有什么用这里就不再描述啦。编码规则查看这篇文章《BASE64编码规则》,也是在网上搜索到的。大致可分为以下两步:一、字节转换(3*8 -> 4*6);二、字符编码。


一、字节转换(3*8 -> 4*6)

    先计算出转码后数组的长度,用来创建新数组及保存转码后的内容。
int desLength = (int) ((src.length + 2) / 3) * 4;

    把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。

进行如下操作:


des[i * 4] = (byte) (src[i * 3] >>> 2);
des[i * 4] &= 0x3f;      // 最高两位置0
des[i * 4 + 1] = (byte) (src[i * 3] << 4 | ((src[i * 3 + 1] >>> 4) & 0x0f));
des[i * 4 + 1] &= 0x3f;  // 最高两位置0
des[i * 4 + 2] = (byte) (src[i * 3 + 1] << 2 | ((src[i * 3 + 2] >>> 6) & 0x03));
des[i * 4 + 2] &= 0x3f;  // 最高两位置0
des[i * 4 + 3] = (byte) (src[i * 3 + 2] & 0x3f);


第二行的目的是将转码后的最高两位置0,第三行最后的 & 0x0f 操作是确保移位后高四位为0。进行这步操作是因为 Java 中的位运算是对32位的整形进行的,对于byte类型会自动转码成int类型后再进行位运算。此时有符号运算(">>")和无符号运算(">>>")效果是一样的,故一定要进行位运算以保证高位为0。

上述操作只对代码量是3的整数倍时有效。当代码量不是3的整数倍时,代码量/3的余数自然就是2或者1。此时,转换结果不够6位的用0来补上相应的位置,之后再在6位的前面补两个0。转换完空出的结果就用就用“=”来补位。

这一步要判断代码的长度,并进行相对应的不同的处理。想了半天,还是用了个小技巧,用Java的异常帮忙获得最后要进行处理的代码。
try {
    // 可以被完全转换的代码,代码量是3的整数倍
} catch (ArrayIndexOutOfBoundsException e) {
    // 特殊处理的代码,及需判断用“=”补位的代码
    if ((src.length % 3) == 2) { // 存在中间项
        des[des.length - 3] = (byte) (src[src.length - 2] << 4 | src[src.length - 1] >>> 4);
        des[des.length - 3] &= 0x3f;
        des[des.length - 2] = (byte) (src[src.length - 1] << 2 | 0x00);
        des[des.length - 2] &= 0x3f;
        des[des.length - 1] = 0x40;
     } else {
        des[des.length - 3] = (byte) (src[src.length - 1] << 4 | 0x00);
        des[des.length - 3] &= 0x3f;
        des[des.length - 2] = 0x40;
        des[des.length - 1] = 0x40;
     }
}

这样,字节转换就完成啦。


二、字符编码

char c[] = new char[des.length];
for (int i = 0; i < des.length; i++) {
    if (des[i] >= 0 && des[i] <= 25)
        c[i] = (char) (des[i] + 'A');
    else if (des[i] >= 26 && des[i] <= 51)
        c[i] = (char) (des[i] - 26 + 'a');
    else if (des[i] >= 52 && des[i] <= 61)
        c[i] = (char) (des[i] -52 + '0');
    else if (des[i] == 62)
        c[i] = '+';
    else if (des[i] == 63)
        c[i] = '/';
    else
        c[i] = '=';
}



解码和编码是一样的步骤,就不再详述啦。

BASE64编码在Java 标准API库中好像没有提供,但sun在JDK中提供了两个类来处理。路径如下:
sun.misc.BASE64Encoder和sun.misc.BASE64Dncoder
用法在下面的代码中用展示。

下面是完整的代码:

import java.io.IOException;


public class Base64 {

    private static byte src[];
    private static byte des[];

    public static char[] encoding(String str) {
        src = str.getBytes();
        int desLength = (int) ((src.length + 2) / 3) * 4;   // 计算目标数组的长度
        des = new byte[desLength];
        // 3*8 转 4*6
        try {
            for (int i = 0; i * 4 < des.length; i++) {
                des[i * 4] = (byte) (src[i * 3] >>> 2);
                des[i * 4] &= 0x3f;
                des[i * 4 + 1] = (byte) (src[i * 3] << 4 | ((src[i * 3 + 1] >>> 4) & 0x0f));
                des[i * 4 + 1] &= 0x3f;
                des[i * 4 + 2] = (byte) (src[i * 3 + 1] << 2 | ((src[i * 3 + 2] >>> 6) & 0x03));
                des[i * 4 + 2] &= 0x3f;
                des[i * 4 + 3] = (byte) (src[i * 3 + 2] & 0x3f);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            if ((src.length % 3) == 2) { // 存在中间项
                des[des.length - 3] = (byte) (src[src.length - 2] << 4 | ((src[src.length - 1] >>> 4) & 0x0f));
                des[des.length - 3] &= 0x3f;
                des[des.length - 2] = (byte) (src[src.length - 1] << 2 | 0x00);
                des[des.length - 2] &= 0x3f;
                des[des.length - 1] = 0x40;
            } else {
                des[des.length - 3] = (byte) (src[src.length - 1] << 4 | 0x00);
                des[des.length - 3] &= 0x3f;
                des[des.length - 2] = 0x40;
                des[des.length - 1] = 0x40;
            }
        }

        // 编码 byte[] -> char[]
        char c[] = new char[des.length];
        for (int i = 0; i < des.length; i++) {
            if (des[i] >= 0 && des[i] <= 25)
                c[i] = (char) (des[i] + 'A');
            else if (des[i] >= 26 && des[i] <= 51)
                c[i] = (char) (des[i] - 26 + 'a');
            else if (des[i] >= 52 && des[i] <= 61)
                c[i] = (char) (des[i] -52 + '0');
            else if (des[i] == 62)
                c[i] = '+';
            else if (des[i] == 63)
                c[i] = '/';
            else
                c[i] = '=';
        }
        return c;
    }

    public static byte[] decoder(String str) {
        // 解码 char[] -> byte[]
        char c[] = str.toCharArray();
        byte[] b = new byte[c.length];
        for (int i = 0; i < c.length; i++) {
            if (c[i] >= 'A' && c[i] <= 'Z')
                b[i] = (byte) (c[i] - 'A');
            else if (c[i] >= 'a' && c[i] <='z')
                b[i] = (byte) (c[i] - 'a' + 26);
            else if (c[i] >= '0' && c[i] <= '9')
                b[i] = (byte) (c[i] - '0' + 52);
            else if (c[i] == '+')
                b[i] = 0x3e;
            else if (c[i] == '/')
                b[i] = 0x3f;
            else
                b[i] = 0x40;
        }

        // 4*6 -> 3*8
        int num = 0; // 记录"="的个数
        if (b[b.length - 1] == 0x40) {
            num++;
            if (b[b.length - 2] == 0x40)
                num++;
        }
        int aLength = b.length / 4 * 3 - num;
        byte [] a = new byte[aLength];
        try {
            for (int i = 0; i * 3 < a.length; i++) {
                a[i * 3] = (byte) ((b[i * 4] << 2) | ((b[i * 4 + 1] >> 4) & 0x03));
                a[i * 3 + 1] = (byte) ((b[i * 4 + 1] << 4) | ((b[i * 4 + 2] >> 2) & 0x0f));
                a[i * 3 + 2] = (byte) ((b[i * 4 + 2] << 6) | (b[i * 4 + 3] & 0x3f));
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            // do nothing
        }
        return a;
    }

    // Test
    public static void main(String[] args) throws IOException {
        String str = new String("Hello,我是翔之骓。英文名是 Cream!");
        char[] temp = Base64.encoding(str);
        System.out.println(temp);
        System.out.println(new String(Base64.decoder(new String(temp))));

        // use sun BASE64 encoding
        sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        System.out.println("系统提供:\n" + encoder.encode(src));
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
        System.out.println(new String(decoder.decodeBuffer(encoder.encode(src))));
    }
}


0
0
分享到:
评论

相关推荐

    base64编码实现

    base64编码规则的java实现.Provides encoding of raw bytes to base64-encoded characters, and decoding of base64 characters to raw bytes.

    base64编码实现版本

    base64编码实现版本

    java实现BASE64编码和解码程序

    实现BASE64编码和解码程序, 在类中实现如下函数并运行测试正确。 BASE64编码算法请在网上查询。 public String encode(byte[] data) { } public byte[] decode(String b) { }

    易语言API实现BASE64编码

    易语言API实现BASE64编码源码,API实现BASE64编码,Base64Enc,CryptBinaryToString

    文件转换为Base64编码

    可以实现将文件转换为Base64编码。可以实现将文件转换为Base64编码。

    2进制与base64编码转换C代码

    需要一个二进制与BASE64相互转换的函数,从网上找...示例中提供二进制与16进制字符串转换函数ConvertHexStrToBin与ConvertBinToHexStr,二进制与BASE64编码转换函数Base64Encode与Base64Decode,在VC6下编译通过可用。

    Delphi用Base64编码实现文件序列化

    该示例可以使文件被序列化为字符串,这样就可以将这个字符串装进XML文档,从而实现通用的文件传输功能。

    android自带base64实现BASE64编码和解码程序完整Java源码

    android 开发中有时会需要用到base64加解密,其实base64并不算是一种加密的算法,只是一种基于64个可打印字符来表示二进制数据的表示方法。 google在android.util下提供了一个Base64工具类,可以很方便的用它encode...

    Data URI scheme详解和使用实例及图片base64编码实现方法

    主要介绍了Data URI scheme详解和使用实例及图片base64编码实现方法,需要的朋友可以参考下

    LabVIEW实现Base64加密解密程序源码

    LabVIEW实现Base64加密解密程序源码,可以作为子VI直接调用,非常方便,经过测试没有问题。base64是一种用64个字符来表示任意二进制数据的方法。base 64编码可以将任意一组字节转换为较长的常见文本字符序列,从而...

    BASE64编码解码_ASM(高性能汇编版)

    算法是查表方式实现,优点:性能好、缺点:码表有几KB的内存占用。跟精易模块的BASE64进行简单测试对比,没啥毛病... 1) 添加 BASE64解码2_ASM 支持未补码的BASE64编码(删除了对标准BASE64编码长度的检测,可能存在B

    vb 图片转base64编码 程序源码

    【程序老媛出品,必属精品,亲测校正,质量保证】 资源名:vb 图片转base64编码 程序源码 ...源码说明: 基于vb编写的实现图片转base64编码程序源码 非常适合借鉴学习 适合人群:新手及有一定经验的开发人员

    base64编码 C++实现

    这个是从github上面看到的一段base64编码算法的c++实现。可以参考一下的

    base64编码与解码C语言实现(带注释说明原理)

    base64编码与解码C语言实现(带注释说明原理) 其中包括:base64编码接口和base64解码接口

    c语言实现base64编码解码

    用c语言实现的base64,包括加密算法和解密算法。

    pb10编码解码base64

    pb10调用base64.dll,实现将图片转换成base64编码,将base64编码转换成图片 函数声明 function long GetFileEncode64(ref string filename, ref string encode64)library "base64" alias for "GetFileEncode64;...

    c语言实现base64编码

    c语言实现base64编码

    jQuery实现文件编码成base64并通过AJAX上传的方法

    本文实例讲述了jQuery实现文件编码成base64并通过AJAX上传的方法。分享给大家供大家参考,具体如下: 使用AJAX是无法直接上传文件的,一般都是新建个iframe在它里面完成表单提交的过程以达到异步上传文件的效果。 ...

    C/C++实现HMAC-SHA1和base64编码

    C语言版的实现HMAC-SHA1和base64编码,已经对C++做了兼容处理,在VS下运行main.c代码,可以得到经过HMAC-SHA1处理后的结果,并且可以运行里面的base64编码函数得到想要的结果,可以用于连接阿里云MQTT

    JavaScript实现Base64编码转换

    简介 Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个...当然,你也可以将图片、文本和音视频转换成二进制序列,再然后转换为Base64编码。我们这里讨论的是如何将二进制转换

Global site tag (gtag.js) - Google Analytics