Base64については、「Base64 – Wikipedia」に詳しくありますが、64種類の印字可能な英数字のみを用いてバイナリデータを含むデータを表現するためのエンコード方式です。Linuxのコマンドには、このエンコードで表現された文字列を扱うための、base64というコマンドがあり、これを使うと、文字列をBase64でエンコードしたり、デコードしたりすることができます(base64 | hiro345)。普段はこれを使っていればいいのですが、Javaプログラムの中で同様の処理をしたい場合は、どうすればよいでしょうか。
いくつか方法がありますが、Apache Commons Codecのライブラリ(Codec – Homeから入手可能)を使う方法と、JavaMailのライブラリ(JavaMail APIから入手可能)を使う方法があります。前者は76文字改行されない文字列となるので、自前で変換が必要なようです。後者は改行されたデータが入手できるので、そのまま使えます。
byteの配列を使った処理になるので、若干複雑な気がするかもしれません。ここではUTF-8でエンコードされた文字を扱うという前提のプログラムとなっています。また、エンコードされた値をbyte配列のままデコードすることは普通はなく、いったん文字で表現された値で保存してから、それを別のところでデコードするはずです。そのため、いったんencodedStrで文字列表現に変換したり、そこからencodedStr.getBytes("UTF-8") のような処理をしてdecodedのbyte配列を取得したりしています。APIの利用方法だけ知りたい人にとっては、冗長な処理に見えるかもしれません。
package org.sssg.soft.sample.codec.base64;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.mail.MessagingException;
import javax.mail.internet.MimeUtility;
import org.apache.commons.codec.binary.Base64;
public class App {
String[] list = { "ABCDEFG", "0123456789", "あいうえお",
"あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも", };
byte[] encoded = new byte[0];
byte[] decoded = new byte[0];
public void commonsBase64() {
for (String str : list) {
String encodedStr = "";
String decodedStr = "";
try {
encoded = Base64.encodeBase64(str.getBytes("UTF-8"));
encodedStr = new String(encoded);
byte[] decodedByte = encodedStr.getBytes("UTF-8");
decoded = Base64.decodeBase64(decodedByte);
decodedStr = new String(decoded);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
print(str, spilit(encodedStr), decodedStr);
}
}
public void javaxmailBase64() {
for (String str : list) {
String encodedStr = "";
String decodedStr = "";
try {
byte[] bs = str.getBytes("UTF-8");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = MimeUtility.encode(baos, "base64");
os.write(bs);
os.close();
encoded = baos.toByteArray();
encodedStr = new String(encoded);
bs = encodedStr.getBytes("UTF-8");
byte[] tmp = new byte[bs.length];
ByteArrayInputStream bais = new ByteArrayInputStream(bs);
InputStream is = MimeUtility.decode(bais, "base64");
int n = is.read(tmp);
decoded = new byte[n];
System.arraycopy(tmp, 0, decoded, 0, n);
decodedStr = new String(decoded);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
print(str, encodedStr, decodedStr);
}
}
public void print(String str, List<String> encodedLines, String decodedStr) {
System.out.println(str);
printLine();
print(encodedLines);
printLine();
System.out.println(decodedStr);
System.out.println("");
System.out.println("");
}
public void print(String str, String encodedStr, String decodedStr) {
System.out.println(str);
printLine();
System.out.println(encodedStr);
printLine();
System.out.println(decodedStr);
System.out.println("");
System.out.println("");
}
public void print(List<String> lines) {
for (String s: lines) {
System.out.println(s);
}
}
private final static int LINE_LENGTH = 76;
public List<String> spilit(String line) {
List<String> lines = new ArrayList<String>();
int i = 0;
while (i<line.length()) {
int end = i + LINE_LENGTH;
if (end > line.length()) {
end = line.length();
}
String s = line.substring(i, end);
lines.add(s);
i += LINE_LENGTH;
}
return lines;
}
private void printLine() {
for (int i = 0; i < LINE_LENGTH; i++) {
System.out.print("-");
}
System.out.println("");
}
public static void main(String[] args) {
App app = new App();
System.out.println("Apache Commons Codec:---------------------");
app.commonsBase64();
System.out.println("javax.mail.internet.MimeUtility:----------");
app.javaxmailBase64();
}
}
実行結果は次のようになるはずです。
ABCDEFG
----------------------------------------------------------------------------
QUJDREVGRw==
----------------------------------------------------------------------------
ABCDEFG
0123456789
----------------------------------------------------------------------------
MDEyMzQ1Njc4OQ==
----------------------------------------------------------------------------
0123456789
あいうえお
----------------------------------------------------------------------------
44GC44GE44GG44GI44GK
----------------------------------------------------------------------------
あいうえお
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも
----------------------------------------------------------------------------
44GC44GE44GG44GI44GK44GL44GN44GP44GR44GT44GV44GX44GZ44Gb44Gd44Gf44Gh44Gk44Gm
44Go44Gq44Gr44Gs44Gt44Gu44Gv44Gy44G144G444G744G+44G/44KA44KB44KC
----------------------------------------------------------------------------
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも
javax.mail.internet.MimeUtility:----------
ABCDEFG
----------------------------------------------------------------------------
QUJDREVGRw==
----------------------------------------------------------------------------
ABCDEFG
0123456789
----------------------------------------------------------------------------
MDEyMzQ1Njc4OQ==
----------------------------------------------------------------------------
0123456789
あいうえお
----------------------------------------------------------------------------
44GC44GE44GG44GI44GK
----------------------------------------------------------------------------
あいうえお
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも
----------------------------------------------------------------------------
44GC44GE44GG44GI44GK44GL44GN44GP44GR44GT44GV44GX44GZ44Gb44Gd44Gf44Gh44Gk44Gm
44Go44Gq44Gr44Gs44Gt44Gu44Gv44Gy44G144G444G744G+44G/44KA44KB44KC
----------------------------------------------------------------------------
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも
コメントありがとうございます。Charset便利ですよね。
失礼しました。なるべく標準以外のライブラリでした。
なるべく標準のライブラリを使いたくないことがあり、java mail apiでの実装の仕方を参考にさせていただきました。ちなみに、UnsupportedEncodingExceptionが嫌いなので、Charsetを使ってString.getByte(), new String()するようにしてます。