站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题用Base64编码与解码

用Base64编码与解码

摘要: 用Base64编码与解码

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="416" height="86" align="left" valign="top">

Base64是网络上最常见的用于加密传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

这样说会不会太抽象了?不怕,我们来看一个例子:

<table border=1> <tr> <td>转换前</td> <td>aaaaaabb</td> <td>ccccdddd</td> <td>eeffffff</td> <td></td> </tr> <tr> <td>转换后</td> <td>00aaaaaa</td> <td>00bbcccc</td> <td>00ddddee</td> <td>00ffffff</td> </tr> </table>
应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。
</td> <td width="268" valign="top"> </td> </tr> </table>

转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)


Table 1: The Base64 Alphabet

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


让我们再来看一个实际的例子,加深印象!

<table border=1> <tr> <td>转换前</td> <td>10101101</td> <td>10111010</td> <td>01110110</td> <td></td> </tr> <tr> <td>转换后</td> <td>00101011</td> <td>00011011</td> <td>00101001</td> <td>00110110</td> </tr> <tr> <td>十进制</td> <td>43</td> <td>27</td> <td>41</td> <td>54</td> </tr> <tr> <td>对应码表中的值</td> <td>r</td> <td>b</td> <td>p</td> <td>2</td> </tr> </table>

所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

下面的Base64编码/解码程序来自网上。

一、用SUN的API解码和编码

import java.io.*;

import sun.misc.BASE64Decoder;

import sun.misc.BASE64Encoder;

public class Base64

{

  public static void main(String[] args) {

    if (args.length == 2) {

      String string = Base64.encode(args[0]);

      Base64.decode(string, args[1]);

    } else

      System.out.println("usage: java Base64 inputFile outputFile");

  }

  public static String encode(String fileName) {

    String string = null;

    try {

      InputStream in = new FileInputStream(fileName);

      // in.available()返回文件的字节长度

      byte[] bytes = new byte[in.available()];

      // 将文件中的内容读入到数组中

      in.read(bytes);

      string = new BASE64Encoder().encode(bytes);

      in.close();

    } catch (FileNotFoundException fe) {

      fe.printStackTrace();

    } catch(IOException ioe) {

      ioe.printStackTrace();

    }

    return string;

  }

  public static void decode(String string, String fileName) {

    try {

      // 解码,然后将字节转换为文件

      byte[] bytes = new BASE64Decoder().decodeBuffer(string);

      ByteArrayInputStream in = new ByteArrayInputStream(bytes);

      byte[] buffer = new byte[1024];

      FileOutputStream out = new FileOutputStream(fileName);

      int bytesum = 0;

      int byteread = 0;

      while ((byteread = in.read(buffer)) != -1) {

        bytesum += byteread;

        out.write(buffer, 0, byteread);

      }

    } catch(IOException ioe) {

      ioe.printStackTrace();

    }

  }

}

二、

/* @author CuCuChen

 * @version $Id$

 */

import java.io.*;

class Base64Helper { 
//从文本文件对象中读取内容并转换为字符数组 public static char[] readChars(File file) { CharArrayWriter caw = new CharArrayWriter(); try { Reader fr = new FileReader(file); Reader in = new BufferedReader(fr); int count = 0; char[] buf = new char[16384]; while ((count=in.read(buf)) != -1) { if (count > 0) caw.write(buf, 0, count); } in.close(); } catch (Exception e) { e.printStackTrace(); } return caw.toCharArray(); }
//从字符串对象中读取内容并转换为字符数组 public static char[] readChars(String string) { CharArrayWriter caw = new CharArrayWriter(); try { Reader sr = new StringReader(string.trim()); Reader in = new BufferedReader(sr); int count = 0; char[] buf = new char[16384]; while ((count=in.read(buf)) != -1) { if (count > 0) caw.write(buf, 0, count); } in.close(); } catch (Exception e) { e.printStackTrace(); } return caw.toCharArray(); }
//从二进制文件对象中读取内容并转换为字节数组 public static byte[] readBytes(File file) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { InputStream fis = new FileInputStream(file); InputStream is = new BufferedInputStream(fis); int count = 0; byte[] buf = new byte[16384]; while ((count=is.read(buf)) != -1) { if (count > 0) baos.write(buf, 0, count); } is.close(); } catch (Exception e) { e.printStackTrace(); } return baos.toByteArray(); }
//写字节数组内容到二进制文件 public static void writeBytes(File file, byte[] data) { try { OutputStream fos = new FileOutputStream(file); OutputStream os = new BufferedOutputStream(fos); os.write(data); os.close(); } catch (Exception e) { e.printStackTrace(); } } //写字符数组内容到文本文件 public static void writeChars(File file, char[] data) { try { Writer fos = new FileWriter(file); Writer os = new BufferedWriter(fos); os.write(data); os.close(); } catch (Exception e) { e.printStackTrace(); } } } public class Base64{ //编码文件对象所指的文件 static public char[] encode(File file){ if (!file.exists()) { System.err.println("错误:文件不存在!"); return null; } return encode(Base64Helper.readBytes(file)); }
//编码文件名所指的文件 static public char[] encode(String filename){ File file = new File(filename); if (!file.exists()) { System.err.println("错误:文件“"+filename+"”不存在!"); return null; } return encode(Base64Helper.readBytes(file)); } //编码传入的字节数组,输出编码后的字符数组 static public char[] encode(byte[] data) { char[] out = new char[((data.length + 2) / 3) * 4]; // // 对字节进行Base64编码,每三个字节转化为4个字符. // 输出总是能被4整除的偶数个字符 // for (int i=0, index=0; i< data.length; i+=3, index+=4) { boolean quad = false; boolean trip = false; int val = (0xFF & (int) data[i]); val <<= 8; if ((i+1) < data.length) { val |= (0xFF & (int) data[i+1]); trip = true; } val <<= 8; if ((i+2) < data.length) { val |= (0xFF & (int) data[i+2]); quad = true; } out[index+3] = alphabet[(quad? (val & 0x3F): 64)]; val >>= 6; out[index+2] = alphabet[(trip? (val & 0x3F): 64)]; val >>= 6; out[index+1] = alphabet[val & 0x3F]; val >>= 6; out[index+0] = alphabet[val & 0x3F]; } return out; } static public byte[] decode(char[] data) { // 程序中有判断如果有回车、空格等非法字符,则要去掉这些字符 // 这样就不会计算错误输出的内容 int tempLen = data.length; for( int ix=0; ix< data.length; ix++ ) { if( (data[ix] > 255) || codes[ data[ix] ] < 0 ) --tempLen; // 去除无效的字符 } // 计算byte的长度 // -- 每四个有效字符输出三个字节的内容 // -- 如果有额外的3个字符,则还要加上2个字节, // 或者如果有额外的2个字符,则要加上1个字节 int len = (tempLen / 4) * 3; if ((tempLen % 4) == 3) len += 2; if ((tempLen % 4) == 2) len += 1; byte[] out = new byte[len]; int shift = 0; int accum = 0; int index = 0; // 一个一个字符地解码(注意用的不是tempLen的值进行循环) for (int ix=0; ix< data.length; ix++) { int value = (data[ix]>255)? -1: codes[ data[ix] ]; if ( value >= 0 ) // 忽略无效字符 { accum <<= 6; shift += 6; accum |= value; if ( shift >= 8 ) { shift -= 8; out[index++] = (byte) ((accum >> shift) & 0xff); } } } //如果数组长度和实际长度不符合,那么抛出错误 if( index != out.length) { throw new Error("数据长度不一致(实际写入了 " + index + "字节,但是系统指示有" + out.length + "字节)"); } return out; } // // 用于编码的字符 // static private char[] alphabet ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray(); // // 用于解码的字节(0-255) // static private byte[] codes = new byte[256]; static { for (int i=0; i<256; i++) codes[i] = -1; for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte)( i - 'A'); for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte)(26 + i - 'a'); for (int i = '0'; i <= '9'; i++) codes[i] = (byte)(52 + i - '0'); codes['+'] = 62; codes['/'] = 63; } public static void main (String [] args){ String key = new String("Spider"); byte[] a = key.getBytes(); char[] b = Base64.encode(a) ; System.out.println(new String(b)); //for(int i=0;i< b.length;i++){ // System.out.println(b[i]); //} byte[] c = Base64. decode(b); System.out.println(new String(c)); } } 运行结果: C:\java>java Base64
U3BpZGVy
Spider

</td> </tr> <tr>


↑返回目录
前一篇: java中的URLEncoder和URLDecoder类
后一篇: 将字母翻译成为摩尔码