StringBuilderとかString#formatとか例外とか
文字列を%<16進数>形式にエスケープする。 - うなの日記のプログラムを弄ってみる。
public static final String escape(String string, String encode) { byte[] bs = null; try { bs = string.getBytes(encode); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException(e); } StringBuilder buff = new StringBuilder(bs.length * 3); for (byte b : bs) { buff.append('%').append(String.format("%02X", b)); } return buff.toString(); }
まず、buffよりbs*1を先に持ってきて、例外はチェックされないIllegalArgumentExceptionでラップして再送するように変更。
例外をどうするかって言うのは難しいんだけど、encodeはプログラマが指定するんじゃね?ってことで。
次にStringBufferをStringBuilderに。String#formatを使ってることから、StringBuilderも問題なし*2。ローカル変数だからマルチスレッドとも無関係。
あと、bsの長さの3倍が変換後の文字列の長さっていうのは分かってるから、初期容量も指定。
for文も拡張for文に。これもJ2SE5.0で追加された構文だけど、分かりやすいので良く使う。
最後、String#formatに渡す引数(第一引数)だけど、"%1$X"から"%02X"に変更。
"%1$X"は、可変長引数の最初の引数を大文字の16進数で、って言う指定で、"%02X"は0詰め、2桁の大文字の16進数で、って言う指定。微妙に違う。
まず、可変長引数が1個固定だから、参照する引数のインデックスを指定する必要はない。これで"%X"。
で、02の部分はちょっと微妙なんだけど、\rやら\nやら\tやらをオリジナルのメソッドに渡すと、
%D%A%9
となってしまう。
これが望んだ動作かどうかは分からないけど、個人的には0がついて欲しいから、0詰めを表す0と、最小幅を表す2をつけて、"%02X"。