`
mycream
  • 浏览: 55600 次
  • 性别: 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编码实现版本

    .NET 中实现 Base64 编码

    在项目Base64Coder中,可能包含了自定义的Base64编码实现,这可能是为了优化性能,提供更灵活的接口,或者处理特定场景下的编码需求。类库可能包括一个或多个类,如Base64Encoder和Base64Decoder,分别负责编码和...

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

    在Delphi编程环境中,我们可以使用Base64编码来实现文件的序列化,即将文件内容转换成一个字符串,然后再从这个字符串中恢复出原始的文件数据,这在处理XML文档、HTTP请求或JSON数据时特别有用。 首先,让我们理解...

    labview 图片缩放 base64编码base64解码

    在LabVIEW中,可以使用字符串函数来实现Base64编码。首先,你需要将图像数据转换为字节串,然后使用Base64编码函数将字节串转换为可读的字符串。这样,图片数据就可以以文本形式在网络上传输,或保存在文本文件中。 ...

    base64 Base64编码 .NET C#

    ### .NET和C#中的Base64编码实现 #### 编码函数:`EncodingString` 此方法接受一个字符串`SourceString`和一个`System.Text.Encoding`对象`Ens`作为参数,并返回该字符串经过Base64编码后的结果。其中,`Ens`对象...

    易语言汇编base64编码

    在易语言汇编中实现Base64编码,通常会涉及以下几个步骤: 1. **数据分割**:将输入的字节数组按照每3个字节一组进行分割,如果最后剩余不足3个字节,需要额外处理。 2. **十六进制转换**:对每3个字节进行转换,...

    base64编码原理,实现方式,全解。

    在提供的`Base64.java`文件中,我们可以看到一个自定义的Base64编码实现。虽然Java 8以后已经有了官方的Base64支持,但这个文件为我们提供了另一种实现方式,可以用来理解Base64编码的工作原理。通过阅读源码,我们...

    Base64.zip_labview base64

    在LabVIEW中,通常我们可以通过编写自定义VI来实现Base64的编码和解码功能,而不依赖于外部库。 在“Base64.zip_labview base64”这个压缩包中,包含了一个名为“Base64.vi”的虚拟仪器(VI)。这个VI是用LabVIEW...

    java和js相互base64编码解码

    下面将详细阐述这两个编程语言中实现Base64编码和解码的方法。 首先,让我们关注Java。在Java 8及更高版本中,已经内置了`java.util.Base64`类来支持Base64编码和解码。例如,在`Base64EnOut.java`文件中,可能会...

    Base64编码解码工具成品+源码

    易语言源码文件"Base64编码解码.e"包含了实现Base64编码和解码功能的算法和用户界面设计。在源码中,我们可以看到易语言如何处理Base64编码的细节,如如何将二进制数据拆分成6位块,如何查找对应的Base64字符,以及...

    Base64编码jar包

    `javabase64-1.3.1.jar`可能提供了这种编码方式,具体实现取决于库的API。 注意,虽然这里介绍的是`javabase64-1.3.1.jar`库,但Java 8及更高版本已经内置了`java.util.Base64`类,提供了一套标准的Base64编码和...

    C语言base64编码解码库

    C语言是编程语言的基础,被广泛应用于系统编程和嵌入式开发,因此一个C语言实现的Base64编码解码库对于开发者来说非常有用。下面将详细介绍这个名为"C语言base64编码解码库"的资源。 该库是从GitHub上获取的,这...

    文件转换为Base64编码

    例如,在Python中,可以使用`base64`模块的`b64encode()`和`b64decode()`函数来实现文件的Base64编码和解码。其他语言如Java、JavaScript、C#等也有相应的API支持。 在实际应用中,Base64编码常用于以下场景: - *...

    易语言 base64编码转图片 如何 提高转换速度.zip

    在易语言中,实现Base64编码到图片的转换通常涉及以下步骤: 1. **读取Base64字符串**:首先,我们需要读取包含Base64编码的字符串,这可以通过读取文本文件或用户输入完成。 2. **Base64解码**:易语言提供了一...

    BASE64编码方法

    在Delphi编程环境中,实现BASE64编码和解码通常涉及到使用内置的TIdEncoderMIME类或者第三方库。以下是对Delphi中BASE64编码和解码的基本步骤的详细解释: 1. **编码过程**: - 首先,原始二进制数据按3个字节一组...

    易语言API实现BASE64编码

    需要注意的是,虽然`CryptBinaryToString`函数可以方便地实现BASE64编码,但在某些情况下,如需要跨平台或者高性能编码,可能需要自己实现BASE64编码算法。易语言提供了丰富的编程结构和函数,开发者可以根据需求...

    Base64系列第四篇 C/C++中使用Base64编码解码(从chromium库中抽取)

    本篇将深入探讨如何在C/C++环境中,利用从Chromium库中提取的代码进行Base64的编码与解码。 首先,Base64编码的原理是将每3个字节(24位)的数据转换为4个6位的字符,然后将这4个6位字符对应到Base64的字符集(包括...

    c++ base64 编码

    `cpp-base64-master`可能是一个开源项目,它提供了C++实现Base64编码和解码的示例。该项目可能包含了一个或多个类或函数,用于进行Base64转换。通常,这样的库会提供一个接口,如`encodeBase64(const std::string& ...

    将图片进行Base64编码后传输

    在IT行业中,图片的传输是常见的操作,...例如,开发者可能使用在线Base64编码工具来快速转换图片,或者在代码编辑器中实现这个功能。总之,Base64编码是IT领域中一种实用的技巧,它简化了二进制数据在网络中的传输。

Global site tag (gtag.js) - Google Analytics