おれのIT日記

2023/04/06 (木)

Java

String.formatでハマった事象


仕事で、こんなコードがあった。(余計な部分は省いてる)
Javaソースのごく一部
String.format("%040x", i);

これは、16進数表記で64文字の文字列を得たい、というコードである。
1f2b3c... みたいなね。
ところが、実際動かしてみると、63文字になる場合があるので書き直しました、と報告を受けた。

それは、値iの先頭が0になる場合で、0が取れちゃう、というものである。

わかる人はこれ見て一発でわかるんでしょうけど、調査した私も最初ダマされた。
"%040x"と指定しているんだけど、64を16進数表現すれば40で合ってるし、0埋め指定もしているし、合ってるじゃん…と。
お気づきの方がほとんどかもしれないが、この桁数指定は16進数じゃありません。10進数で指定するべきなのです。
64桁の文字列が得たいなら、"%064x"と書くべきだった。

"%040x"の場合、String.formatは、40文字に足りなければ、40文字に達するまで0埋めをするが、40文字を超えた分を切り捨てることはせず「そのまま」表示する。
だから、頭が0にならない値を食わせた場合は、期待どおり64桁の文字列を表示してくれるので、適当にテストしていたせいか誰も気づかなかった…というわけ。

あまりこういうコード書く場面がないので、多くのメンバーはうろ覚えであり、16進数で堂々と書いているのを見せられると、心理的に「そうだったか」と納得して、別の部分にミスがあるのでは?!と探してしまう、ということではないかしら。
ちゃんとしたソフト屋さんなら、こんなことないのだろうけど、ね。