用Base64编码与解码

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

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

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

转换前 aaaaaabb ccccdddd eeffffff
转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

    应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

    转换后,我们用一个码表来得到我们想要的字符串(也就是最终的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


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

转换前 10101101 10111010 01110110
转换后 00101011 00011011 00101001 00110110
十进制 43 27 41 54
对应码表中的值 r b p 2

所以上面的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
转自:http://www.java3z.com/cwbwebhome/article/article2/2407.html?id=1095

你可能感兴趣的:(exception,String,File,buffer,import,byte)