2009-05-27 17 views
6

Czy istnieje prosty sposób dekodowania łańcucha base64 przy użyciu TYLKO JAVA 1.5 BIBLIOTEK?Decode base64 String Java 5

Muszę używać języka Java 1.5 ze względu na problemy ze zgodnością między platformami między systemami Windows i Mac OS X (tylko Mac 10.5 obsługuje język Java 1.6, wszystko poniżej 10.5 ma domyślnie Java 1.5).

obiektu "sun.misc.Base64Decoder" istnieje w Javie 6, ale nie w Javie 5.

Odpowiedz

9

Nie, to nie jest możliwe na podstawie tuż przy użyciu JDK 5.0.

Musisz wdrożyć własną implementację (nie jest to takie trudne) lub najlepiej użyć jednej z implementacji open source. Istnieje wiele w tym Codec Commons, które zapewnia Base64 http://commons.apache.org/codec/api-release/org/apache/commons/codec/binary/Base64.html

JavaMail zapewnia również kodowanie Base64/dekodowania poprzez MimeUtility który również ma podane do druku kodowania itd ...

http://java.sun.com/products/javamail/javadocs/javax/mail/internet/MimeUtility.html

+0

javax.mail doesnt wydaje się istnieć również w Javie 5. ale właśnie pobrałem axis.jar z apache i mogłem użyć klasy "org.apache.axis.encoding.Base64" i to działa dobrze –

+2

Żaden Javamail nie istnieje jako osobny plik do pobrania. Szczerze mówiąc, nie użyłbym wersji Axis, ponieważ spowoduje to upuszczenie wielu innych rzeczy, których nie potrzebujesz (chyba, że ​​je wyciągniesz) - użyj zamiast tego Commons Codec. – Jon

8

Apache Commons Codec

FYI, należy używać tego nawet w Javie 6. Don't use classes in sun.*

+0

Byłoby dobrze, gdyby można było podać powody, dlaczego nie - w ten sposób ludzie mogą dokonać świadomej opinii, jeśli powody nadal istnieją lub są po prostu wolą autorów ences – sweetfa

+2

Dlatego zdanie "Nie używaj klas w słońcu." jest hiperłączem do strony internetowej pod adresem java.sun.com pod tytułem "Dlaczego programistom nie wolno pisać programów, które wywołują" pakiety "słońca" – Jherico

5

Oto moja wersja - powinien być całkowicie samodzielny:

public class Base64 
{ 

// ***************************************************************************** 
// INSTANCE PROPERTIES 
// ***************************************************************************** 

private String       lineSeparator; 
private int        lineLength; 

// ***************************************************************************** 
// INSTANCE CONSTRUCTION/INITIALIZATON/FINALIZATION, OPEN/CLOSE 
// ***************************************************************************** 

public Base64() { 
    lineSeparator=System.getProperty("line.separator"); 
    lineLength=0; 
    } 

// ***************************************************************************** 
// INSTANCE METHODS 
// ***************************************************************************** 

public String encode(byte[] bin) { 
    return encode(bin,0,bin.length); 
    } 
/** 
* Encode an array of bytes as Base64. 
* It will be broken into lines if the line length is not 0. If broken into lines, 
* the last line is not terminated with a line separator. 
* 
* param ba   The byte array to encode. 
*/ 
public String encode(byte[] bin, int str, int len) { 
    int         ol;          // output length 
    StringBuffer      sb;          // string buffer for output(must be local for recursion to work). 
    int         lp;          // line position(must be local for recursion to work). 
    int         el;          // even multiple of 3 length 
    int         ll;          // leftover length 

    // CREATE OUTPUT BUFFER 
    ol=(((len+2)/3)*4); 
    if(lineLength!=0) { 
     int lines=(((ol+lineLength-1)/lineLength)-1); 
     if(lines>0) { ol+=(lines*lineSeparator.length()); } 
     } 
    sb=new StringBuffer(ol); 
    lp=0; 

    // EVEN MULTIPLES OF 3 
    el=(len/3)*3; 
    ll=(len-el); 
    for(int xa=0; xa<el; xa+=3) { 
     int cv; 
     int c0,c1,c2,c3; 

     if(lineLength!=0) { 
      lp+=4; 
      if(lp>lineLength) { sb.append(lineSeparator); lp=4; } 
      } 

     // get next three bytes in unsigned form lined up, in big-endian order 
     cv =(bin[xa+str+0]&0xFF); cv<<=8; 
     cv|=(bin[xa+str+1]&0xFF); cv<<=8; 
     cv|=(bin[xa+str+2]&0xFF); 

     // break those 24 bits into a 4 groups of 6 bits, working LSB to MSB. 
     c3=cv&0x3F; cv >>>=6; 
     c2=cv&0x3F; cv >>>=6; 
     c1=cv&0x3F; cv >>>=6; 
     c0=cv&0x3F; 

     // Translate into the equivalent alpha character emitting them in big-endian order. 
     sb.append(ENCODE[c0]); 
     sb.append(ENCODE[c1]); 
     sb.append(ENCODE[c2]); 
     sb.append(ENCODE[c3]); 
     } 

    // LEFTOVERS 
    if(lineLength!=0 && ll>0) { 
     lp+=4; 
     if(lp>lineLength) { sb.append(lineSeparator); lp=4; } 
     } 
    if(ll==1) { 
     sb.append(encode(new byte[] { bin[el+str], 0, 0 }).substring(0,2)).append("==");   // Use recursion so escaping logic is not repeated, replacing last 2 chars with "==". 
     } 
    else if(ll==2) { 
     sb.append(encode(new byte[] { bin[el+str], bin[el+str+1], 0 }).substring(0,3)).append("="); // Use recursion so escaping logic is not repeated, replacing last char and "=". 
     } 
    if(ol!=sb.length()) { throw new RuntimeException("Error in Base64 encoding method: Calculated output length of "+ol+" did not match actual length of "+sb.length()); } 
    return sb.toString(); 
    } 

public byte[] decode(String b64) { 
    return decode(b64,0,b64.length()); 
    } 

/** 
* Decode a Base64 string to an array of bytes. 
* The string must have a length evenly divisible by 4 (not counting line separators and other 
* ignorable characters, like whitespace). 
*/ 
public byte[] decode(String b64, int str, int len) { 
    byte[]        ba;          // target byte array 
    int         dc;          // decode cycle (within sequence of 4 input chars). 
    int         rv;          // reconstituted value 
    int         ol;          // output length 
    int         pc;          // padding count 

    ba=new byte[(len/4)*3];              // create array to largest possible size. 
    dc=0; 
    rv=0; 
    ol=0; 
    pc=0; 

    for(int xa=0; xa<len; xa++) { 
     int ch=b64.charAt(xa+str); 
     int value=(ch<=255 ? DECODE[ch] : IGNORE); 
     if(value!=IGNORE) { 
      if(value==PAD) { 
       value=0; 
       pc++; 
       } 
      switch(dc) { 
       case 0: { 
        rv=value; 
        dc=1; 
        } break; 

       case 1: { 
        rv<<=6; 
        rv|=value; 
        dc=2; 
        } break; 

       case 2: { 
        rv<<=6; 
        rv|=value; 
        dc=3; 
        } break; 

       case 3: { 
        rv<<=6; 
        rv|=value; 

        // Completed a cycle of 4 chars, so recombine the four 6-bit values in big-endian order 
        ba[ol+2]=(byte)rv; rv>>>=8; 
        ba[ol+1]=(byte)rv; rv>>>=8; 
        ba[ol]=(byte)rv; ol+=3; 
        dc=0; 
        } break; 
       } 
      } 
     } 
    if(dc!=0) { 
     throw new ArrayIndexOutOfBoundsException("Base64 data given as input was not an even multiple of 4 characters (should be padded with '=' characters)."); 
     } 
    ol-=pc; 
    if(ba.length!=ol) { 
     byte[] b2=new byte[ol]; 
     System.arraycopy(ba, 0, b2, 0, ol); 
     ba=b2; 
     } 
    return ba; 
    } 

/** 
* Set maximum line length for encoded lines. 
* Ignored by decode. 
* @param len  Length of each line. 0 means no newlines inserted. Must be a multiple of 4. 
*/ 
public void setLineLength(int len) { 
    this.lineLength=(len/4)*4; 
    } 

/** 
* Set the line separator sequence for encoded lines. 
* Ignored by decode. 
* Usually contains only a combination of chars \n and \r, but could be any chars except 'A'-'Z', 'a'-'z', '0'-'9', '+' and '/'. 
* @param linsep  Line separator - may be "" but not null. 
*/ 
public void setLineSeparator(String linsep) { 
    this.lineSeparator=linsep; 
    } 

// ***************************************************************************** 
// STATIC PROPERTIES 
// ***************************************************************************** 

static private final char[]    ENCODE=new char[64];     // translation array for encoding 
static private final int[]    DECODE=new int[256];     // translation array for decoding 
static private final int    IGNORE=-1;        // flag for values to ignore when decoding 
static private final int    PAD=-2;         // flag value for padding value when decoding 

static private final Base64    BASE64=new Base64();     // default converter 

// ***************************************************************************** 
// STATIC INIT & MAIN 
// ***************************************************************************** 

static { 
    for(int xa=0; xa<=25; xa++) { ENCODE[xa]=(char)('A'+xa); }     // 0..25 -> 'A'..'Z' 
    for(int xa=0; xa<=25; xa++) { ENCODE[xa+26]=(char)('a'+xa); }    // 26..51 -> 'a'..'z' 
    for(int xa=0; xa<= 9; xa++) { ENCODE[xa+52]=(char)('0'+xa); }    // 52..61 -> '0'..'9' 
    ENCODE[62]='+'; 
    ENCODE[63]='/'; 

    for(int xa=0; xa<256; xa++) { DECODE[xa]=IGNORE;  }      // set all chars to IGNORE, first 
    for(int xa=0; xa< 64; xa++) { DECODE[ENCODE[xa]]=xa; }      // set the Base 64 chars to their integer byte values 
    DECODE['=']=PAD; 
    } 

// ***************************************************************************** 
// STATIC METHODS 
// ***************************************************************************** 

static public String toString(byte[] dta) { 
    return BASE64.encode(dta); 
    } 

static public String toString(byte[] dta, int str, int len) { 
    return BASE64.encode(dta,str,len); 
    } 

static public byte[] toBytes(String b64) { 
    return BASE64.decode(b64); 
    } 

static public byte[] toBytes(String b64, int str, int len) { 
    return BASE64.decode(b64,str,len); 
    } 

} // END PUBLIC CLASS