【PHP実践|実務向け】PHPでファイルサイズを人間が読みやすい形式(Human Readable)に変換する方法

1. 導入

Webアプリケーションを開発していると、ファイルアップロード機能などで取得した「バイト単位」の数値を、ユーザーにとって分かりやすい「MB」や「GB」に変換して表示したい場面が多々あります。生のバイト数(例:1073741824)を見せられても、ユーザーは直感的に容量を把握できません。本記事では、この課題を解決するための汎用的な変換ロジックを解説します。

2. 基礎知識

コンピュータのデータ量は一般的に「1KB = 1024バイト」という2進数ベースで計算されます。ファイルサイズの変換には、この1024という数値を累乗していく仕組みが必要です。PHPでは、対数関数である log() を使用することで、その数値がどの単位(KB, MB, GB…)に属するのかを効率的に判定できます。

3. 実装/解決策

今回作成する関数では、以下の3つの要件を満たすように設計します。
・自動単位判定:渡された数値を自動的に適切な単位に割り当てる。
・精度調整:小数点以下の桁数を指定可能にする。
・可読性向上:カンマ区切りの有無を選択可能にする。

論理的には、log(数値, 1024) を計算してインデックスを取得し、配列から対応する単位名を取り出します。定義した単位を超えた大きな数値が入力された場合でも、最大単位(例:PB)で表示を維持する堅牢な構造にします。

4. サンプルプログラム

以下のコードは、実務でもそのまま利用できる設計になっています。

  • バイト数を人間が読みやすい形式(KB, MB, GBなど)に変換する関数
  • @param int|float $size バイト数
  • @param int $dec 小数点以下の桁数(-1で自動判定)
  • @param bool $separate カンマ区切りにするかどうか
  • @return string 変換後の文字列
  • /
    function byte_format($size, $dec = -1, $separate = false) {
    $units = [‘B’, ‘KB’, ‘MB’, ‘GB’, ‘TB’, ‘PB’];

    // 0バイトの場合はそのまま返す
    if ($size <= 0) return '0B'; // どの単位階層に属するかを計算 $digits = floor(log($size, 1024)); $max_digit = count($units) - 1; // 定義した単位を超えた場合の処理 $over = false; if ($digits > $max_digit) {
    $digits = $max_digit;
    $over = true;
    }

    // 単位に合わせて数値を変換
    $num = $size / pow(1024, $digits);

    // 小数点以下の桁数処理
    if ($dec > -1) {
    $num = number_format($num, $dec, ‘.’, ”);
    }

    // カンマ区切りの適用
    if ($separate) {
    $num = number_format((float)$num, ($dec > 0 ? $dec : 0));
    }

    return $num . $units[$digits];
    }

    // 使用例
    $file_size = 109951162777600; // 約100TB
    echo byte_format($file_size, 2, true); // 出力: 100.00TB
    ?>

    5. 応用・注意点

    実務で使用する際は、以下の点に注意してください。

    ・巨大な数値の扱い: 32bit環境のPHPでは大きな整数を扱えない場合があります。64bit環境で実行することを確認してください。
    ・小数点以下の処理: number_format を使うと戻り値が文字列になります。後の計算でこの数値を使う場合は、戻り値の型に注意が必要です。
    ・単位の定義: ネットワーク通信やストレージ容量の表記では「1KB = 1000バイト」として計算されるケースも存在します。要件に合わせて単位のベースとなる数値(1024)を調整してください。

    この関数を共通ライブラリ(Helperクラスなど)に含めておくと、プロジェクト全体で一貫した単位表示が可能になります。ぜひ活用してみてください。

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