base 64 en java


Ce petit programme permet de faire la conversion (encodage ou decodage) d'une source de données en base64 en utilisant le langage java.


/**
 * Title:
 * Description: encoder et decode en base64
 * class base64
 *
 * @author Isaac Mekueko
 * @version 1.0
 */

public final class Base64 {
  static private final byte PADDING            = ( byte ) '=';
  static private final int  SIGN               = -128;
  static private byte [] Encodebase64Alphabet  = new byte[64];
  static private byte [] alphaDecode           =new byte[256];



  static {
    for(int i=0;i<=25;i++)
      Encodebase64Alphabet[i]=(byte)('A'+i);
    for(int i=26,j=0;i<=51;i++,j++)
      Encodebase64Alphabet[i]=(byte)('a'+j);
    for(int i=52,j=0;i<=61;i++,j++)
      Encodebase64Alphabet[i]=(byte)('0'+j);
      Encodebase64Alphabet[62]=(byte)('+');
      Encodebase64Alphabet[63]=(byte)('/');


      // decode
    for(int i=0;i<256;i++)
      alphaDecode[i]=-1;
    for(int i='A',j=0;i<='Z';i++,j++)
       alphaDecode[i]=(byte)j;
    for(int i='a',j=26;i<='z';i++,j++)
       alphaDecode[i]=(byte)j;
    for(int i='0',j=52;i<='9';i++,j++)
       alphaDecode[i]=(byte)j;
    alphaDecode['+']=62;
    alphaDecode['/']=63;

  }

  /*****************************************
   * encode array byte from 0-255 to base64
   * @param array byte
   * @return array byte
   * ****************************************/
  static public byte [] encode (byte [] DataByte){
    int numberDataBit=DataByte.length*8;
    int numberDataBitMODULO24=numberDataBit%24;
    int numberDataBitBY24=numberDataBit/24;
    byte []EncodeData=null;

    if(numberDataBitMODULO24==0) EncodeData=new byte[numberDataBitBY24*4];
      else EncodeData=new byte[(numberDataBitBY24+1)*4];
    byte Rshift2_b1,High_b2,Rshift6_b3,b1,b2,b3 ,e2,e3,e4 ;
    int IndexDataByte,IndexEncodeData,i;
    for( i=0;i<numberDataBitBY24;i++){
      IndexDataByte=3*i;
      IndexEncodeData=4*i;

      b1=DataByte[IndexDataByte];
      b2=DataByte[IndexDataByte+1];
      b3=DataByte[IndexDataByte+2];

      Rshift2_b1=((b1&SIGN)==0) ? (byte)(b1>>2) : (byte)(b1>>>2);
          High_b2=((b2&SIGN)==0) ? (byte)(b2>>4) : (byte)(b2>>>4);
      Rshift6_b3=((b2&SIGN)==0) ? (byte)(b3>>6) : (byte)(b3>>>6);

      e2=(byte)(((b1&0x3)<<4)|High_b2);
      e3=(byte)(((b2&0xF)<<2)|Rshift6_b3);
      e4=(byte)(b3&0x3F);
      EncodeData[IndexEncodeData]=  Encodebase64Alphabet[Rshift2_b1];
      EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
      EncodeData[IndexEncodeData+2]=Encodebase64Alphabet[e3];
      EncodeData[IndexEncodeData+3]=Encodebase64Alphabet[e4];

    }//end for
    IndexDataByte=3*i;
    IndexEncodeData=4*i;

    if(numberDataBitMODULO24==16){
      b1=DataByte[IndexDataByte];
      b2=DataByte[IndexDataByte+1];
      Rshift2_b1=((b1&SIGN)==0)  ? (byte)(b1>>2) : (byte)(b1>>>2);
          High_b2=((b2&SIGN)==0) ? (byte)(b2>>4) : (byte)(b2>>>4);
      e2=(byte)(((b1&0x3)<<4)|High_b2);
      e3=(byte)((b2&0xF)<<2);
      e4=PADDING;
      EncodeData[IndexEncodeData]=  Encodebase64Alphabet[Rshift2_b1];
      EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
      EncodeData[IndexEncodeData+2]=Encodebase64Alphabet[e3];
      EncodeData[IndexEncodeData+3]=e4;
    } else
        if(numberDataBitMODULO24==8)
          {
              b1=DataByte[IndexDataByte];
              Rshift2_b1=((b1&SIGN)==0)  ? (byte)(b1>>2) : (byte)(b1>>>2);
              e2=(byte)((b1&0x3)<<4);
              e3=PADDING;
              e4=PADDING;
              EncodeData[IndexEncodeData]=  Encodebase64Alphabet[Rshift2_b1];
              EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
              EncodeData[IndexEncodeData+2]=e3;
              EncodeData[IndexEncodeData+3]=e4;

          }

    return EncodeData;
  }

  /**************************************
   * encode string from 0-255 to base64
   * @param string
   * @return String
   * *************************************/

  static public String encode(String str){
    return new String(encode(str.getBytes()));
 }

 /**********************************************
  *  decode array byte from base64 to char 0-255
  *  @param array byte
  *  @return array byte
  *********************************************/
 public static byte[] decode(byte []DataByte){
    if(!isByteInBase64(DataByte))return null;
    int numberDataBit=DataByte.length*6;
    int numberGroup_3bit=numberDataBit/24;
    byte []DecodeData=null;
    byte b1,b2,b3,b4,d1,d2,d3,ch1,ch2,ch3,ch4;
    ch3=DataByte[DataByte.length-2];
    ch4=DataByte[DataByte.length-1];
    if(ch3!=PADDING&&ch4!=PADDING)
      DecodeData=new byte[numberGroup_3bit*3];
      else if(ch3==PADDING)
        DecodeData=new byte[(numberGroup_3bit*3)-2];
        else if(ch4==PADDING)
        DecodeData=new byte[(numberGroup_3bit*3)-1];

    int decodeIndex,encodeIndex;

    for(int i=0; i<numberGroup_3bit;i++){
      decodeIndex=3*i;
      encodeIndex=4*i;
      ch1=DataByte[encodeIndex];
      ch2=DataByte[encodeIndex+1];
      ch3=DataByte[encodeIndex+2];
      ch4=DataByte[encodeIndex+3];
      b1=alphaDecode[ch1];
      b2=alphaDecode[ch2];
      b3=alphaDecode[ch3];
        b4=alphaDecode[ch4];
      if(ch3!=PADDING&&ch4!=PADDING){
        d1=(byte)((b1<<2)|(b2>>>4));
        d2=(byte)((b2<<4)|(b3>>2));
        d3=(byte)((b3<<6)|b4);
        DecodeData[decodeIndex]=d1;
        DecodeData[decodeIndex+1]=d2;
        DecodeData[decodeIndex+2]=d3;
      }else
        if(ch3==PADDING){// 1 char
          d1=(byte)((b1<<2)|(b2>>>4));
          DecodeData[decodeIndex]=d1;
        }
         else
            if(ch4==PADDING){ // 2char
              d1=(byte)((b1<<2)|(b2>>>4));
              d2=(byte)((b2<<4)|(b3>>2));
              DecodeData[decodeIndex]=d1;
              DecodeData[decodeIndex+1]=d2;
            }

    }//end for
return DecodeData;
 }

 /**
  *  decode base64 string into characters from 0-255
  *  @param string
  *  return string
  **/
 public static String decode(String str){
     return new String(decode(str.getBytes()));
 }
/**
 * check if the byte belong to The Base64 Alphabet
 * @param octet
 * @return bolean value
 * */
 private static boolean isByteInBase64(byte octet){
  if(octet==PADDING||alphaDecode[octet]!=-1) return true;
    else
      return false;
 }
private static boolean isByteInBase64(byte []arraybyte){
  int len=arraybyte.length;
  for(int i=0;i<len;i++){
    if(!isByteInBase64(arraybyte[i]))
      return false;
  }
  return true;
 }
}
José a rencontré quelques soucis dans son implementation et nous propose sa version de la méthode encode. Au passage il a adapté pour formatter en lignes de 19 quartets compatible envoie par mail.

  public byte [] encode (byte [] DataByte)throws Exception{
    int numberDataBit=DataByte.length*8;
    int numberDataBitMODULO24=numberDataBit%24;
    int numberDataBitBY24=numberDataBit/24;
    int nrQuad=numberDataBitBY24;
    if (numberDataBitMODULO24!=0) nrQuad++;
    int nrlig=(nrQuad>0) ? (nrQuad-1)/19 : 0;

    byte []EncodeData=new byte[nrQuad*4+nrlig*2];

    byte Rshift2_b1,High_b2,Rshift6_b3,b1,b2,b3 ,e2,e3,e4 ;
    int IndexDataByte,IndexEncodeData,i;
    IndexDataByte=0;
    IndexEncodeData=0;
    nrQuad=0;
    for( i=0;i<numberDataBitBY24;i++){
      if(nrQuad==19)
      {
         EncodeData[IndexEncodeData]=(byte)'\r';
         EncodeData[IndexEncodeData+1]=(byte)'\n';
         IndexEncodeData += 2;
         nrQuad=0;
      }

      b1=DataByte[IndexDataByte];
      b2=DataByte[IndexDataByte+1];
      b3=DataByte[IndexDataByte+2];

      Rshift2_b1=(byte)((b1>>>2) & 0x3F);
         High_b2=(byte)((b2>>>4) & 0x0F);
      Rshift6_b3=(byte)((b3>>>6) & 0x03);

      e2=(byte)(((b1&0x3)<<4)|High_b2);
      e3=(byte)(((b2&0xF)<<2)|Rshift6_b3);
      e4=(byte)(b3&0x3F);

      EncodeData[IndexEncodeData]=  Encodebase64Alphabet[Rshift2_b1];
      EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
      EncodeData[IndexEncodeData+2]=Encodebase64Alphabet[e3];
      EncodeData[IndexEncodeData+3]=Encodebase64Alphabet[e4];

      IndexDataByte += 3;
      IndexEncodeData += 4;
      nrQuad++;
    }//end for

    if(numberDataBitMODULO24==16){
      if(nrQuad==19)
      {
         EncodeData[IndexEncodeData]=(byte)'\r';
         EncodeData[IndexEncodeData+1]=(byte)'\n';
         IndexEncodeData += 2;
      }
      b1=DataByte[IndexDataByte];
      b2=DataByte[IndexDataByte+1];
      Rshift2_b1=((b1&SIGN)==0)  ? (byte)(b1>>2) : (byte)(b1>>>2);
          High_b2=((b2&SIGN)==0) ? (byte)(b2>>4) : (byte)(b2>>>4);
      e2=(byte)(((b1&0x3)<<4)|High_b2);
      e3=(byte)((b2&0xF)<<2);
      e4=PADDING;
      EncodeData[IndexEncodeData]=  Encodebase64Alphabet[Rshift2_b1];
      EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
      EncodeData[IndexEncodeData+2]=Encodebase64Alphabet[e3];
      EncodeData[IndexEncodeData+3]=e4;
    } else
        if(numberDataBitMODULO24==8)
          {
             if(nrQuad==19)
             {
                EncodeData[IndexEncodeData]=(byte)'\r';
                EncodeData[IndexEncodeData+1]=(byte)'\n';
                IndexEncodeData += 2;
             }
              b1=DataByte[IndexDataByte];
              Rshift2_b1=((b1&SIGN)==0)  ? (byte)(b1>>2) : (byte)(b1>>>2);
              e2=(byte)((b1&0x3)<<4);
              e3=PADDING;
              e4=PADDING;
              EncodeData[IndexEncodeData]=  Encodebase64Alphabet[Rshift2_b1];
              EncodeData[IndexEncodeData+1]=Encodebase64Alphabet[e2];
              EncodeData[IndexEncodeData+2]=e3;
              EncodeData[IndexEncodeData+3]=e4;

          }

    return EncodeData;
  }
et la méthode
 public static String decode(String str){
     return new String(decode(str.getBytes()));
 }
peut avantageusement être écrite
 public static String decode(String str){
     return new String(decode(str.getBytes("ISO-8859-1")));
 }
dans les cas où c'est nécessaire (si String est une donnée binaire)