Javaでバイトの単位(KB,MB,GB)をわかりやすくする
1 * 1024 * 1024 で1メガバイト、みたいなやつをよく見る。
コードレビューしていると、1000 だったり 1024 だったり、気を利かせて 1_024 と書かれていたり、たまに 124 とか 1240 とタイポしていたりと、結構揺らぎがち。また、KB/MB/GBかKiB/MiB/GiBか、みたいな議論になったりすることもあって面倒。
TimeUnit のように、Javaで単位をわかりやすくできるライブラリはないかと思い、調べたのでメモ。
SpringのDataSize
Springに、各バイト単位を変換する DataSize 、および単位自体を表す列挙型の DataUnit があった。
DataSize#of...bytes(long) メソッドで DataSize インスタンスを生成し、 to...Bytes() で指定した単位の long に変換する。また、 DataSize#parse(CharSequence) で文字列の解析も可能。
DataUnit の値名は KILOBYTES, MEGABYTES, GIGABYTES だが、それぞれ2の10乗、20乗、30乗なので、 long 値は 1,024, 1,048,576, 1,073,741,824 となる。
// 単位系がわかっている場合、それに応じたofメソッドを使用 assert DataSize.ofMegabytes(1).toBytes() == 1 * 1024 * 1024; // of(long, DataUnit)で、任意の単位に変換可能 assert DataSize.of(2, DataUnit.GIGABYTES).toMegabytes() == 2 * 1024; // parse(CharSequence[, DataUnit])で文字列を解析 assert DataSize.parse("20MB").toBytes() == 20 * 1024 * 1024;
Apache Commons
Commons IOの FileUtils に、各単位の long および BigInteger が static で宣言されている。
ONE_KB, ONE_MB, ONE_GB などあるが、 DataSize と同様、それぞれ 1,024, 1,048,576, 1,073,741,824 となる。
FileUtils.byteCountToDisplaySize(long) というメソッドで、バイト数を文字列に変換できるが、小数点以下が無視されるので扱いづらい。
その他
byteunits というライブラリもあった。こちらは KB と KiB などを区別する模様。
振り返り
今日のJava開発であれば、Springはだいたい使っていると思うので、 DataSize を使っておけばシンプルになりそう。
また、SpringもCommonsも1024の倍数をKB、MB、GBとして使っているので、下手にKiBなど使わず、KBとかにしておくのが無難かと思った。
余談
以下のスタックオーバーフローの記事で、数値から文字列に変換するスニペットが記載されている。
どうも、スタックオーバーフローで最もコピーされたスニペットらしいが、間違っていた模様。