Base64をデコードしてみました

 

プログラム上で処理しなければならないことは色々ありますが
クラスライブラリとして提供されるものも多いので、上手に活用するのが早道です。

毎度、管理人イガジーです。

でも、プログラミングの練習としては、変換処理のひとつふたつは
作ってみるのが良いでしょう。

という訳で、Base64 のデコード処理を自前で作ってみました。
Base64については、Wikipediaに詳しい説明があります。→こちら

要するに、A〜Z, a〜z, 0〜9 の文字(+2文字)で、6ビットデータを表す
ようにしたものがBase64です。

デコードは、このA〜Z, a〜z, 0〜9 の文字からもとの8ビットデータに戻すことです。
例えば、QUJDREVGRw== をデコードすると ABCDEFG になります。

まず、それらの文字を6ビットデータに変換する処理を考えます。

int dec1(int x){ // 6bits
	int r=0;
	switch (x) {
	case '+':
	case '-':
		r=62;break;
	case '/':
	case '_':
		r=63;break;
	case '=':r=0;break;
	default:
		if ((x>='A')&&(x<='Z')) r=x-'A';
		else if ((x>='a')&&(x<='z')) r=x-'a'+26;
		else if ((x>='0')&&(x<='9')) r=x-'0'+52;
//		else System.out.print("Err ");
		break;
	}
	return r;
}

if 文が処理の中心です。
書き方によっては && を使わないようにすることもできますが
分かりやすさを優先しました。

switch〜caseを使わずに、全部 else if で書いてしまうこともできます。
好みですが、switch〜caseの方が、62,63 の文字を変更しやすいと
思ったので上記の書き方にしました。

さて、次は6ビットを8ビットにはめ込む処理です。つまり
123456 123456 123456 123456

12345612 34561234 56123456
にするのですが、4つの6ビットを3つの8ビットにする処理をベタで書き下すことにします。

その場合に面倒なのが、4つずつ処理しようとしても、3つしか無いとか
2つしかない、という場合の異常処理です。

毎回チェックするのも面倒なので、最初に入力データに3つぶんの”===”を
足しておくことにします。

入出力は、普通ファイルなのでしょうが、手軽さを考えて引数で入力し
printfで出力する形にしました(改造はご自由に)。

public class Base64Dec {
	int d[]=new int[3];
	int dt;

	Base64Dec(String as[]){
		for (int i=0;i<as.length;++i) {
			System.out.println(as[i]);
			String t=as[i]+"===";
			for (int j=0;j<as[i].length();j+=4) {
//				12345612 34561234 56123456
				// QUJDREVGRw==
				// ABCDEFG
				d[0]=(dec1(t.charAt(j))*4)&0xFF; // <<2

				dt=dec1(t.charAt(j+1));
				d[0]+=(dt/16); // >>4
				d[1]=(dt*16)&0xFF; // <<4

				dt=dec1(t.charAt(j+2));
				d[1]+=(dt/4); // >>2
				d[2]=(dt*64)&0xFF; // <<6

				d[2]+=dec1(t.charAt(j+3));
				for (int k=0;k<3;++k) {
					System.out.printf(" %02X", d[k]);
					if ((d[k]>' ')&&(d[k]<'z')) System.out.printf("(%c)", d[k]);
				}
			}
		}
	}
	int dec1(int x){ // 6bits
		int r=0;
		switch (x) {
		case '+':
		case '-':
			r=62;break;
		case '/':
		case '_':
			r=63;break;
		case '=':r=0;break;
		default:
			if ((x>='A')&&(x<='Z')) r=x-'A';
			else if ((x>='a')&&(x<='z')) r=x-'a'+26;
			else if ((x>='0')&&(x<='9')) r=x-'0'+52;
//			else System.out.print("Err ");
			break;
		}
		return r;
	}
/*
	void printbin6(int x) {
		int m=0x20;
		for (int i=0;i<6;++i) {
			if ((x & m)!=0) System.out.print("1");
			else System.out.print("0");
			m=m/2;
		}
		System.out.print(" ");
	}
	void printbin8(int x) {
		int m=0x80;
		for (int i=0;i<8;++i) {
			if ((x & m)!=0) System.out.print("*");
			else System.out.print("_");
			m=m/2;
		}
		System.out.print(" ");
	}
*/
	public static void main(String[] args) {
		new Base64Dec(args);
	}

}

printbin8(), printbin6() はデバッグ用の2進数表示メソッドです。
上記を眺めるだけでなく、ぜひエンコードも作ってみてください。

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)