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 および BigIntegerstatic で宣言されている。

ONE_KB, ONE_MB, ONE_GB などあるが、 DataSize と同様、それぞれ 1,024, 1,048,576, 1,073,741,824 となる。

FileUtils.byteCountToDisplaySize(long) というメソッドで、バイト数を文字列に変換できるが、小数点以下が無視されるので扱いづらい。

その他

byteunits というライブラリもあった。こちらは KBKiB などを区別する模様。

github.com

振り返り

今日のJava開発であれば、Springはだいたい使っていると思うので、 DataSize を使っておけばシンプルになりそう。

また、SpringもCommonsも1024の倍数をKB、MB、GBとして使っているので、下手にKiBなど使わず、KBとかにしておくのが無難かと思った。

余談

以下のスタックオーバーフローの記事で、数値から文字列に変換するスニペットが記載されている。

stackoverflow.com

どうも、スタックオーバーフローで最もコピーされたスニペットらしいが、間違っていた模様。

programming.guide