ファイルサイズをフォーマットする方法

Java

ファイルサイズの数値をそのまま表示するのではなく、1.2 MB のように、直感的に理解できる単位へ変換する処理です。
if文を重ねて実装することも可能ですが、対数を利用するアプローチを紹介します。

FileFormatUtils クラス

import java.text.DecimalFormat;

public final class FileFormatUtils {

    /**
     * ファイルサイズ(バイト)を人が読みやすい単位(B, KB, MB...)に変換します。
     * 
     * @param bytes ファイルサイズ(バイト単位)。nullも許容されます。
     * @return フォーマットされた文字列。例: "1.2 MB"。
     *         入力がnullまたは負の値の場合は "0 B" を返します。
     */
    public static String formatFileSize(Long bytes) {
        if (bytes == null || bytes < 0) {
            return "0 B";
        }
        if (bytes < 1024) {
            return bytes + " B";
        }

        // 単位
        String[] units = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
        
        // 単位のインデックスを算出
        int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024));
        
        // 想定を超える巨大な値に対する安全対策
        if (digitGroups >= units.length) {
            digitGroups = units.length - 1;
        }

        // フォーマット
        double formattedSize = bytes / Math.pow(1024, digitGroups);
        String format = new DecimalFormat("#,##0.#").format(formattedSize);
        return format + " " + units[digitGroups];
    }

    /**
     * ユーティリティクラスのインスタンス化を防止します。
     */
    private FileFormatUtils() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }
}

対数の利用

ファイルサイズの単位が1024のべき乗(1024^0, 1024^1, 1024^2…)で変化することに着目します。この「べき乗」の指数部分を効率的に求める数学的な道具が「対数」です。

int digitGroups = (int) (Math.log10(bytes) / Math.log10(1024));

この一行は、Javaの標準ライブラリで提供されている常用対数(log10)と、対数の底の変換公式を利用して、「bytesは1024の何乗に最も近いか」を算出しています。結果として得られる整数 digitGroups は、units配列のインデックスに直接対応します。

このアプローチにより、コードはデータ(units配列)とロジック(対数計算)に分離され、将来的にZB(ゼタバイト)などの単位を追加する際も、配列に文字列を追加するだけで対応可能になります。

防御的プログラミング

下記は予期せぬ入力値を想定しています。

if (bytes == null || bytes < 0) {
    return "0 B";
}

ファイルサイズが物理的に負の値になることはありませんが、プログラム上のエラーやデータ破損により、負の値が渡される可能性は否定できません。このガード節は、後続の Math.log10 が不正な値(負数)で失敗するのを防ぎ、メソッド全体の安定性を保証する重要な役割を果たします。

同様に、巨大な値が入力された場合に備え、digitGroupsが配列の範囲を超えないようにクリップする処理も、堅牢性を高める上で不可欠です。

外部ライブラリ

このような機能はフォーマットが少し異なりますが、 Apache Commons IO の FileUtils.byteCountToDisplaySize() で提供されています。

まとめ

ファイルサイズをフォーマットするコードの紹介でした。
もしプロジェクトで Apache Commons IO が利用可能なら、迷わず FileUtils.byteCountToDisplaySize() を使いましょう。

ライブラリを追加できない事情がある場合や、自作したいという場合は、このコードが参考になれば幸いです。

記事が良かったら、ぜひ応援してください!

Buy Me a Coffee

Java
スポンサーリンク
シェアする

コメント

タイトルとURLをコピーしました