Encode/Decode to/from Base64

From CodeCodex

Implementations

Java

As seen in this HowTo, the sun.misc.BASE64Encoder/Decoder or creating your own Base64 handling are the more common way to deal with Base64 encoding/decoding. Here some alternatives which are maybe easier (and safer) to use.

Using javax.mail.internet.MimeUtility

import javax.mail.internet.MimeUtility;
import java.io.*;

public class Base64Utils {
    public static byte[] encode(byte[] b) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        OutputStream b64os = MimeUtility.encode(baos, "base64");
        b64os.write(b);
        b64os.close();
        return baos.toByteArray();
     }
     
     public static byte[] decode(byte[] b) throws Exception {
        ByteArrayInputStream bais = new ByteArrayInputStream(b);
        InputStream b64is = MimeUtility.decode(bais, "base64");
        byte[] tmp = new byte[b.length];
        int n = b64is.read(tmp);
        byte[] res = new byte[n];
        System.arraycopy(tmp, 0, res, 0, n);
        return res;
     }  

    public static void main(String[] args) throws Exception {
        String test = "realhowto";
        
        byte res1[] = Base64Utils.encode(test.getBytes());
        System.out.println(test + " base64 -> " + java.util.Arrays.toString(res1));
        System.out.println(new String(res1));
        byte res2[] = Base64Utils.decode(res1);
        System.out.println("");
        System.out.println( java.util.Arrays.toString(res1) + " string --> " 
          + new String(res2));
        
        /*
         * output
         * realhowto base64 -> 
         *     [99, 109, 86, 104, 98, 71, 104, 118, 100, 51, 82, 118]
         *     cmVhbGhvd3Rv
         * [99, 109, 86, 104, 98, 71, 104, 118, 100, 51, 82, 118] 
         *     string --> realhowto
         */
    }

}

Using Apache Commons Codec Apache Commons Codec provides implementations of common encoders and decoders such as Base64, Hex, Phonetic and URLs. Download at http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Base64;

public class Codec {
  public static void main(String[] args) {
    try {
      String clearText = "Hello world";
      String encodedText;

      // Base64
      encodedText = new String(Base64.encodeBase64(clearText.getBytes()));
      System.out.println("Encoded: " + encodedText);
      System.out.println("Decoded:" 
          + new String(Base64.decodeBase64(encodedText.getBytes())));
      //    
      // output :
      //   Encoded: SGVsbG8gd29ybGQ=
      //   Decoded:Hello world      
      //
    } 
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

MiGBase64

MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

Seed7

The "encoding.s7i" library defines the functions toBase64 and fromBase64. The following example uses this functions:

const proc: checkBase64 (in string: stri) is func
  begin
    writeln(literal(toBase64(stri)));
    if fromBase64(toBase64(stri)) <> stri then
      writeln("Base64 conversions do not work for " <& literal(stri));
      writeln(" " <& literal(fromBase64(toBase64(stri))));
    end if;
  end func;

In the "encoding.s7i" library toBase64 and toBase64 are defined as:

const func string: toBase64 (in string: stri) is func
  result
    var string: result is "";
  local
    const string: coding is "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var integer: index is 1;
    var integer: subIndex is 1;
    var char: ch is ' ';
    var integer: threeBytes is 0;
    var string: fourBytes is "    ";
    var integer: posToAddNewline is 58;
  begin
    for index range 1 to length(stri) step 3 do
      threeBytes := 0;
      for subIndex range index to index + 2 do
        if subIndex <= length(stri) then
          ch := stri[subIndex];
          if ch >= '\256\' then
            raise RANGE_ERROR;
          end if;
        else
          ch := '\0\';
        end if;
        threeBytes := (threeBytes << 8) + ord(ch);
      end for;
      fourBytes @:= [1] coding[succ( threeBytes >> 18)];
      fourBytes @:= [2] coding[succ((threeBytes >> 12) mod 64)];
      fourBytes @:= [3] coding[succ((threeBytes >>  6) mod 64)];
      fourBytes @:= [4] coding[succ( threeBytes        mod 64)];
      if index = posToAddNewline then
        result &:= "\n";
        posToAddNewline +:= 57;
      end if;
      result &:= fourBytes;
    end for;
    index := length(result);
    if length(stri) rem 3 = 2 then
      result @:= [index] '=';
    elsif length(stri) rem 3 = 1 then
      result @:= [index] '=';
      result @:= [pred(index)] '=';
    end if;
  end func;

Original source: [1]

const func string: fromBase64 (in string: stri) is func
  result
    var string: result is "";
  local
    const array integer: decode is [] (                      # -1 is illegal
        62, -1, -1, -1, 63,                                  # + /
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,              # 0 - 9
        -1, -1, -1,  0, -1, -1, -1,                          # =
         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  # A - M
        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  # N - Z
        -1, -1, -1, -1, -1, -1,
        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  # a - m
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51); # n - z
    var integer: index is 1;
    var integer: subIndex is 1;
    var integer: number is 0;
    var integer: fourBytes is 0;
    var string: threeBytes is "   ";
  begin
    while index <= length(stri) - 3 do
      if stri[index] >= '+' then
        fourBytes := 0;
        for subIndex range index to index + 3 do
          number := decode[ord(stri[subIndex]) - ord(pred('+'))];
          if number = -1 then
            raise RANGE_ERROR;
          end if;
          fourBytes := (fourBytes << 6) + number;
        end for;
        threeBytes @:= [1] chr( fourBytes >> 16);
        threeBytes @:= [2] chr((fourBytes >>  8) mod 256);
        threeBytes @:= [3] chr( fourBytes        mod 256);
        result &:= threeBytes;
        index +:= 4;
      elsif stri[index] = '\n' then
        incr(index);
      elsif stri[index] = '\r' or stri[succ(index)] = '\n' then
        index +:= 2;
      else
        raise RANGE_ERROR;
      end if;
    end while;
    if index <> succ(length(stri)) then
      raise RANGE_ERROR;
    end if;
    if stri[length(stri) - 1 len 2] = "==" then
      result := result[.. length(result) - 2];
    elsif length(stri) >= 1 and stri[length(stri)] = '=' then
      result := result[.. pred(length(result))];
    end if;
  end func;

Original source: [2]