BASE64

気が向いたので、ちょっと作ってみました。
ビット単位に扱うのが面倒だったので、3バイト=4文字ごとに処理してみました。

package util;

import java.util.ArrayList;
import java.util.List;

public class Base64 {
    public static final String TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    public String encode(byte[] data) {
        StringBuffer result = new StringBuffer();
        int pos = 0;
        for (; pos+2<data.length; pos+=3) {
            // 3バイトを4文字に変換する。
            byte b0 = data[pos];
            byte b1 = data[pos+1];
            byte b2 = data[pos+2];
            // 6ビットごとに区切る。
            int i0 = (b0 >> 2) & 0x3F;              // --00 0000
            int i1 = (b0 << 4 | b1 >> 4) & 0x3F;    // --00 1111
            int i2 = (b1 << 2 | b2 >> 6) & 0x3F;    // --11 1122
            int i3 = b2 & 0x3F;                     // --22 2222
            // 文字に変換
            char c0 = TABLE.charAt(i0);
            char c1 = TABLE.charAt(i1);
            char c2 = TABLE.charAt(i2);
            char c3 = TABLE.charAt(i3);
            result.append(c0);
            result.append(c1);
            result.append(c2);
            result.append(c3);
        }
        // 端数
        if (data.length - pos == 2) {
            // 3バイトを4文字に変換する。
            byte b0 = data[pos];
            byte b1 = data[pos+1];
            // 6ビットごとに区切る。
            int i0 = (b0 >> 2) & 0x3F;
            int i1 = (b0 << 4 | b1 >> 4) & 0x3F;
            int i2 = (b1 << 2) & 0x3F;
            // 文字に変換
            char c0 = TABLE.charAt(i0);
            char c1 = TABLE.charAt(i1);
            char c2 = TABLE.charAt(i2);
            result.append(c0);
            result.append(c1);
            result.append(c2);
            result.append('=');
        }
        else if (data.length - pos == 1) {
            // 3バイトを4文字に変換する。
            byte b0 = data[pos];
            // 6ビットごとに区切る。
            int i0 = (b0 >> 2) & 0x3F;
            int i1 = (b0 << 4) & 0x3F;
            // 文字に変換
            char c0 = TABLE.charAt(i0);
            char c1 = TABLE.charAt(i1);
            result.append(c0);
            result.append(c1);
            result.append('=');
            result.append('=');
        }
        return result.toString();
    }
    public byte[] decode(String text) {
        List bytes = new ArrayList();
        // 4文字ずつ変換する。
        for (int i=0; i<text.length(); i+=4) {
            char c0 = text.charAt(i);
            char c1 = text.charAt(i+1);
            char c2 = text.charAt(i+2);
            char c3 = text.charAt(i+3);
            
            int b0 = TABLE.indexOf(c0);
            int b1 = (c1!='=') ? TABLE.indexOf(c1): 0;
            int b2 = (c2!='=') ? TABLE.indexOf(c2): 0;
            int b3 = (c3!='=') ? TABLE.indexOf(c3): 0;
            // 0000 0011  1111 2222  2233 3333 
            byte d0 = (byte)(b0 << 2 | b1 >> 4);
            byte d1 = (byte)(b1 << 4 | b2 >> 2);
            byte d2 = (byte)(b2 << 6 | b3);
            if (c1!='=') bytes.add(new Byte(d0));
            if (c2!='=') bytes.add(new Byte(d1));
            if (c3!='=') bytes.add(new Byte(d2));
//          System.out.println(Integer.toHexString(b));
        }
        // バイトのリストをバイト配列に変換
        byte[] result = new byte[bytes.size()];
        for (int i=0; i<bytes.size(); i++) {
            result[i] = ((Byte) bytes.get(i)).byteValue();
        }
        return result;
    }
    
    public static void main(String[] args) {
        String result = new Base64().encode(new byte[]{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47});
        System.out.println("result="+result);
        byte[] bytes = new Base64().decode("QUJDREVGRw==");
        System.out.println(TextUtil.dump(bytes));
    }
}