スマートカードアプリを作る時にAPDUを扱う場面などに、しばしば16進数の文字列をバイト列にしたり、バイト列を2進数の文字列にしたりすることがあったので、まとめておこうと思いました。
変数名はsrc(変換前) => val(変換後)
int => OO進数(String) ①
String val = String.format("%04d", Integer.valueOf(src));
- 10進数は
"%d"
、8進数なら"%o"
、16進数なら"%x"
-
Integer.valueOf()
でInteger型にキャストしている。 -
"%04d"
は0埋め4桁で表示するという意味。
int => OO進数(String) ②
String val = Integer.toBinaryString(src); // 2進
String val = Integer.toOctalString(src); // 8進
String val = Integer.toHexString(src); // 16進
- Stringのフォーマットをしたいときは①がおすすめ
OO進数(String) => int ①
int val = Integer.decode(src);
int val = Integer.decode("0" + src); // 8進
int val = Integer.decode("0x" + src); // 16進
- srcが"0x0fa2"のように前方に"0x"の表記を持ってる場合、何進数かを自動判別してint型に直してくれるので便利。
OO進数(String) => int ②
int val = Integer.parseInt(src, 2);
int val = Integer.parseInt(src, 8);
int val = Integer.parseInt(src, 16);
- 何進数かもともとわかってるときはこっちが便利。
OO進数(String) => XX進数(String)
上の2つを組み合わせれば良いので割愛
16進数(String) => バイト列(byte[]) ①
byte[] val = Hex.decodeHex(src.toCharArray()); // 16進数
- Apache Commons CodecのHexクラスが必要
- srcの英字は小文字
- srcの長さが奇数だとエラー。
16進数(String) => バイト列(byte[]) ②
byte[] val = DatatypeConverter.parseHexBinary(src);
- srcの英字は小文字でも大文字でも可
- srcの長さが奇数だとエラー。
バイト列(byte[]) => 16進数(String) ①
String val = new String(Hex.encodeHex(src));
- Apache Commons CodecのHexクラスが必要
バイト列(byte[]) => 16進数(String) ②
String val = "";
for(byte b : src){
val += String.format("%02x", (b & 0xff));
}
バイト列(byte[]) => 2進数(String)
String val = "";
for(byte b : src){
for(int i=0; i<8; i++){
val += String.format("%d", (b & 0x80)/0x80);
b <<= 1;
}
}
- 内部のfor文は、「bの最左ビット(0か1)をvalに付け加え、bを左シフトする。」という動作を8回(1byte=8bit分)繰り返してる。
2進数(String) => バイト列(byte[])
int num = Integer.parseInt(src, 2);
String hex = String.format("%x", Integer.valueOf(num));
while(hex.length() < src.length()/4) hex = "0" + hex;
byte[] val = DatatypeConverter.parseHexBinary(hex);
- 「 2進数(String)=>int 」 -> 「 int=>16進数(String) 」 -> 「 16進数(String)=>バイト列(byte[]) 」という流れ。
- 3行目のwhile文は、たとえばsrcが "00000110" の時に、hexが **"c"**ではなく、 "0c" となるようにするため。