java
Base64にエンコードしたものをデコードするプログラムです。(汎用性が低いのは仕様です)コンパイルは通ったのですが、実行したら以下のエラーが出てきました。
C:\Users\Owner\Documents\javadev>java Base64Decode2 hello.dat hello2.txt
java.lang.ArrayIndexOutOfBoundsException: 97
at Base64Decode2.decode(Base64Decode2.java:51)
at Base64Decode2.main(Base64Decode2.java:23)
指定の行を見ても原因がよく分かりません。とても初歩的な質問なのかもしれませんが、お願いします。
以下がプログラムコードです
import java.io.*;
public class Base64Decode2 {
public static void main(String[] args) {
// 変換テーブル
char[] table = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
InputStream in = null; // 入力データ
OutputStream out = null; // 出力先
try {
in = new FileInputStream(args[0]);
out = new FileOutputStream(args[1]);
char[] cs;
while ((cs=read4(in)) != null) {
int[] buf = decode(cs, table);//ここが問題?
for (int i=0; i<buf.length; i++) {
System.out.print(buf[i]+", ");
}
System.out.println();
int[] buf2 = convert6to8(buf);
write3(out, buf2);
}
} catch (Exception e) {
e.printStackTrace(); // 例外の情報を表示する
} finally { // in, out を閉じる
try {
in.close();
out.close();
}
catch (Exception e) {
}
}
}
/**
* 8ビットの2進数の列を復号化する.
* @param cs
* @param table 符号テーブル
* @return
*/
public static int[] decode(char[] cs, char[] table) {
int[] buf = new int[cs.length];
for (int i=0; i<buf.length; i++) {
buf[i] = table[cs[i]];//ここが問題?
}
return buf;
}
public static int[] convert6to8(int[] buf) {
String b;
int[] buf2;
if (buf.length == 2) {
b = toBinary(buf[0], 6);
buf2 = new int[1];
buf2[0] = fromBinary(b.substring(0, 8));
} else if (buf.length == 3) {
b = toBinary(buf[0], 6) + toBinary(buf[1], 6);
buf2 = new int[2];
buf2[0] = fromBinary(b.substring(0, 8));
buf2[1] = fromBinary(b.substring(8, 16));
} else {
b = toBinary(buf[0], 6) + toBinary(buf[1], 6) + toBinary(buf[2], 6);
buf2 = new int[3];
buf2[0] = fromBinary(b.substring(0, 8));
buf2[1] = fromBinary(b.substring(8, 16));
buf2[2] = fromBinary(b.substring(16, 24));
}
return buf2;
}
/**
* バイト列 bt の数を順に出力する.
* @param bt 数の配列。長さは 3以下. 各数は8ビットの整数
*/
public static void write3(OutputStream out, int[] bt) throws IOException {
for (int i=0; i<3; i++) {
if (i<bt.length) {
out.write(bt[i]);
}
}
}
/**
* in から文字を最大4つ読み出す.
* @param in 入力ストリーム
* @return 文字の配列。配列長は最大4. 入力終了したときには null を返す.
*/
public static char[] read4(InputStream in) throws IOException {
char[] bs;
int n0=in.read();
int n1=in.read();
int n2=in.read();
int n3=in.read();
if (n0 < 0) { // 読み込み終了
bs = null;
} else if (n2 < 0 || (char) n2=='=') {
bs = new char[2];
bs[0] = (char) n0;
bs[1] = (char) n1;
} else if (n3 < 0 || (char) n3=='=') {
bs = new char[3];
bs[0] = (char) n0;
bs[1] = (char) n1;
bs[2] = (char) n2;
} else {
bs = new char[4];
bs[0] = (char) n0;
bs[1] = (char) n1;
bs[2] = (char) n2;
bs[3] = (char) n3;
}
return bs;
}
/**
* 数を読み取って、nビットの2進数を表す文字列に変換する
* @param bt 1バイトの数
* @param n 2進数のビット数
* @return 2進数を表す文字列
*/
public static String toBinary(int bt, int n) {
String s = Integer.toBinaryString(bt);
for (int i=s.length(); i<n; i++) {
s = "0" + s;
}
return s;
}
/**
* 2進数を表す文字列を数に変換する
* @param b 2進数を表す文字列
* @return b が表す数
*/
public static int fromBinary(String b) {
return Integer.parseInt(b, 2);
}
}
お礼
tom11さん、どうもありがとうございます。このリンク先のものを見ると、base64エンコードを行っています。これは行わずに、単にpackの結果だけを得たい場合は、getBytesだけで終わればいいってことでしょうか。