Chinaunix首页 | 论坛 | 博客
  • 博客访问: 476284
  • 博文数量: 55
  • 博客积分: 1867
  • 博客等级: 上尉
  • 技术积分: 587
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-29 01:33
文章分类

全部博文(55)

文章存档

2013年(1)

2012年(2)

2011年(16)

2010年(11)

2009年(5)

2008年(10)

2007年(8)

2006年(2)

分类: 系统运维

2008-01-31 19:18:23

一直以来总是被browser和server之间各种编码所困惑,尤其在多语言支持上非常头大。
今天参考网络上一些Base64编码传送的思路,写了JavaScript的Base64编解码的过程,主要目的是,当需要把一个多语言的字符串传到server时,对字符串进行Base64编码,反过来当从server得到字符串时,进行Base64解码,同时希望Base64编码后的东西,不会被browser或server的各种编码方法,如 javascript:escape()改变。

思路:
1. JavaScript 的String都是Unicode的,也就是UCS-2
2. 为了保证Base64后的码较短,UCS-2先转换成UTF-8编码
3. 选择不会被javascript:escape()编码的Base64字符集

代码如下:

// JavaScript代码:


StringUtil = {
Base64Chars:
    "ABCDEFGHIJKLMNOP" +
    "QRSTUVWXYZabcdef" +
    "ghijklmnopqrstuv" +
    "wxyz0123456789@*" +
    "-",
/**
 * Encode a string to a Base64 string follow Bse64 regular.
 * @param s, a normal string
 * @return a Base64 string
 */

base64Encode: function(s){
    if(!s || s.length == 0) return s;

    var d = "";
    var b = this.ucs2_utf8(s);
    var b0, b1, b2, b3;
    var len = b.length;
    var i = 0;
    while(i < len){
       var tmp = b[i++];
       b0 = (tmp & 0xfc) >> 2;
       b1 = (tmp & 0x03) << 4;
       if(i < len){
          tmp = b[i++];
          b1 |= (tmp & 0xf0) >> 4;
          b2 = (tmp & 0x0f) << 2;
          if(i< len){
             tmp = b[i++];
             b2 |= (tmp & 0xc0) >> 6;
             b3 = tmp & 0x3f;
          }else{
             b3 = 64; // 1 byte "-" is supplement

          }
       }else{
          b2 = b3 = 64; // 2 bytes "-" are supplement

       }

       d+=this.Base64Chars.charAt(b0);
       d+=this.Base64Chars.charAt(b1);
       d+=this.Base64Chars.charAt(b2);
       d+=this.Base64Chars.charAt(b3);
    }

    return d;
    
},
/**
 * Decode a Base64 string to a string follow Base64 regular.
 * @param s, a Base64 string
 * @return a normal string
 */

base64Decode: function(s){
    if(!s) return null;
    var len = s.length;
    if(len%4 != 0){
       throw s+" is not a valid Base64 string.";
    }

    var b = new Array();
    var i=0, j=0, e=0, c, tmp;
    while(i < len){
       c = this.Base64Chars.indexOf(s.charAt(i++));
       tmp = c << 18;
       c = this.Base64Chars.indexOf(s.charAt(i++));
       tmp |= c << 12;
       c = this.Base64Chars.indexOf(s.charAt(i++));
       if(c < 64){
          tmp |= c << 6;
          c = this.Base64Chars.indexOf(s.charAt(i++));
          if(c < 64){
             tmp |= c;
          }else{
             e = 1;
          }
       }else{
          e = 2;
          i++;
       }

       b[j+2] = tmp & 0xff;
       tmp >>= 8;
       b[j+1] = tmp & 0xff;
       tmp >>= 8;
       b[j+0] = tmp & 0xff;
       j += 3;
       
    }
    
    b.splice(b.length-e, e);

    return this.utf8_ucs2(b);
    
},
/**
 * Encodes a ucs2 string to a utf8 integer array.
 * @param s, a string
 * @return an integer array
 */

ucs2_utf8: function(s){
    if (!s) return null;
    var d = new Array();
    if (s == "") return d;

    var c = 0, i = 0, j = 0;
    var len = s.length;
    while(i < len){
       c = s.charCodeAt(i++);
       if(c <= 0x7f){
          // 1 byte

          d[j++] = c;
       }else
       if((c >= 0x80) && (c <= 0x7ff)){
          // 2 bytes

          d[j++] = ((c >> 6) & 0x1f) | 0xc0;
          d[j++] = (c & 0x3f) | 0x80;
       }else{
          // 3 bytes

          d[j++] = (c >> 12) | 0xe0;
          d[j++] = ((c >> 6) & 0x3f) | 0x80;
          d[j++] = (c & 0x3f) | 0x80;
       }
    }
    
    return d;
},
/**
 * Encodes a utf8 integer array to a ucs2 string.
 * @param s, an integer array
 * @return a string
 */

utf8_ucs2: function(s){
    if(!s) return null;
    var len = s.length;
    if(len == 0) return "";

    var d = "";
    var c = 0, i = 0, tmp = 0;
    while(i < len){
       c = s[i++];
       if((c & 0xe0) == 0xe0){
          // 3 bytes

          tmp = (c & 0x0f) << 12;
          c = s[i++];
          tmp |= ((c & 0x3f) << 6);
          c = s[i++];
          tmp |= (c & 0x3f);
       }else
       if((c & 0xc0) == 0xc0){
          // 2 bytes

          tmp = (c & 0x1f) << 6;
          c = s[i++];
          tmp |= (c & 0x3f);
       }else{
          // 1 byte

          tmp = c;
       }
       
       d += String.fromCharCode(tmp);
    }
    
    return d;
},

}



//以下是相应的Java代码:


public final class StringUtil {
    
    public static final String Base64Chars =
        "ABCDEFGHIJKLMNOP" +
        "QRSTUVWXYZabcdef" +
        "ghijklmnopqrstuv" +
        "wxyz0123456789@*" +
        "-"; // supplement

            
    /**
     * Encoding a string to a string follow the Base64 regular
     *
     * @param s
     * @return
     */

    public static String base64Encode(final String s){
        if(s == null || s.length()==0) return s;
        
        byte[] b = null;
        try {
            b = s.getBytes("UTF-8");
        } catch (java.io.UnsupportedEncodingException e) {
            e.printStackTrace();
            return s;
        }
        
        return base64EncodeFoArray(b);
        
    }
    /**
     * Encoding a byte array to a string follow the Base64 regular.
     *
     * @param s byte array
     * @return
     */

    public static String base64EncodeFoArray(final byte[] s){
        if(s == null) return null;
        if(s.length == 0) return "";
        
        StringBuffer buf = new StringBuffer();
        
        int b0, b1, b2, b3;
        int len = s.length;
        int i=0;
        while(i < len){
            byte tmp = s[i++];
            b0 = (tmp & 0xfc) >> 2;
            b1 = (tmp & 0x03) << 4;
            if(i < len){
                tmp = s[i++];
                b1 |=(tmp & 0xf0) >> 4;
                b2 = (tmp & 0x0f) << 2;
                if(i < len){
                    tmp = s[i++];
                    b2 |= (tmp & 0xc0) >> 6;
                    b3 = tmp & 0x3f;
                }else{
                    b3 = 64; // 1 byte "-" is supplement

                }
            }else{
                b2 = b3 = 64;// 2 bytes "-" are supplement

            }
            
            buf.append(Base64Chars.charAt(b0));
            buf.append(Base64Chars.charAt(b1));
            buf.append(Base64Chars.charAt(b2));
            buf.append(Base64Chars.charAt(b3));
        }
        
        return buf.toString();
    }
    
    /**
     * Decoding a string to a string follow the Base64 regular.
     *
     * @param s
     * @return
     */

    public static String base64Decode(final String s){
        byte[] b = base64DecodeToArray(s);
        if(b == null) return null;
        if(b.length == 0) return "";
        
        try {
            return new String(b, "UTF-8");
        } catch (java.io.UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
        
    }
    /**
     * Decoding a string to a byte array follow the Base64 regular
     *
     * @param s
     * @return
     */

    public static byte[] base64DecodeToArray(final String s){
        if(s == null) return null;
        
        int len = s.length();
        if(len == 0) return new byte[0];
        if(len%4 != 0){
            throw new java.lang.IllegalArgumentException(s);
        }
        
        byte[] b = new byte[(len/4)*3];
        int i = 0, j=0, e = 0, c, tmp;
        while(i<len){
            c = Base64Chars.indexOf((int)s.charAt(i++));
            tmp = c << 18;
            c = Base64Chars.indexOf((int)s.charAt(i++));
            tmp |= c<< 12;
            c = Base64Chars.indexOf((int)s.charAt(i++));
            if(c < 64) {
                tmp |= c << 6;
                c = Base64Chars.indexOf((int)s.charAt(i++));
                if(c < 64){
                    tmp |= c;
                }else{
                    e = 1;
                }
            }else{
                e = 2;
                i++;
            }
            
            b[j+2] = (byte)(tmp & 0xff);
            tmp >>= 8;
            b[j+1] = (byte)(tmp & 0xff);
            tmp >>= 8;
            b[j+0] = (byte)(tmp & 0xff);
            j += 3;
        }
        
        if(e != 0){
            len = b.length - e;
            byte[] copy = new byte[len];
            System.arraycopy(b, 0, copy, 0, len);
            return copy;
        }
        
        return b;
    }
    
    /**
     * @param args
     */

    public static void main(String[] args) {
    String s0 = "AB枫知`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?";
    String s1 = base64Encode(s0);
    System.err.println(s0+" --> "+ s1);
    String s2 = base64Decode(s1);
    System.err.println(s1+" --> "+s2);
    
    }

}

阅读(2688) | 评论(5) | 转发(0) |
给主人留下些什么吧!~~

hoodng2008-10-30 12:01:36

什么叫标准的Base64? 是码表,还是编码规则,我想只要是Base64的规则就可以了,以上提供的码表目的是故意挑选的,主要是希望Base64编码后的东西,不会被browser或server的各种编码方法,如 javascript:escape()改变。

chinaunix网友2008-10-22 23:03:10

编码不正确,试一下中文的编码就知道了,跟标准的BASE64不一样

chinaunix网友2008-10-22 23:02:14

编码不正确,试一下中文的编码就知道了,跟标准的BASE64不一样

chinaunix网友2008-05-29 19:57:49

发现一个问题, 当“枫知” 两个字一起转时, 在服务器 (ASP.NET(C#)) 没办法正常的反转回来。 其它的正常, 不知道为什么, 好像有些字放到一起就会乱~~

chinaunix网友2008-05-28 15:15:53

很不错~~~ 正考虑编码的事情。