在開發下載中心、文件管理器等功能時,將位元組數值轉換為 KB、MB、GB 等易讀單位是常見需求。本文介紹兩種經典實現方式,並分析其優缺點與適用場景。
<?php
/**
* 將位元組轉為人類可讀格式(對數法)
* @param int|float $size 位元組數
* @return string 如 "1.23 MB"
*/
static function convert($size) {
$unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
// log($size, 1024) 算出級數,floor 取整
$i = floor(log($size, 1024));
// 防止超出陣列範圍
$i = max(0, min($i, count($unit) - 1));
return round($size / pow(1024, $i), 2) . ' ' . $unit[$i];
}
?>
特點:代碼極其精簡,利用數學對數直接定位單位級數,無循環開銷,適合極簡風格或嵌入式場景。注意 log(0) 會報警,實際使用建議先判斷 $size <= 0。
<?php
/**
* 將位元組轉為人類可讀格式(迭代法)
* @param int|float $size 位元組數
* @return string 如 "1.23 MB"
*/
function HumanReadableFilesize($size) {
$mod = 1024;
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
$i = 0;
while ($size >= $mod && $i < count($units) - 1) {
$size /= $mod;
$i++;
}
return round($size, 2) . ' ' . $units[$i];
}
?>
特點:邏輯清晰,易於擴展(如自定義進制 1000、增加單位後綴),邊界控制更直觀,適合企業級項目維護。
<?php
namespace App\Utils;
class FileSizeFormatter
{
public const UNITS_SI = ['B', 'kB', 'MB', 'GB', 'TB', 'PB']; // 1000 進制
public const UNITS_IEC = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']; // 1024 進制
/**
* @param int|float $bytes
* @param array $units 單位陣列
* @param int $precision 小數位
* @param int $base 進制 (1000|1024)
*/
public static function format($bytes, $units = self::UNITS_IEC, $precision = 2, $base = 1024) {
if ($bytes < 0) $bytes = 0;
$i = 0;
while ($bytes >= $base && $i < count($units) - 1) {
$bytes /= $base;
$i++;
}
return round($bytes, $precision) . ' ' . $units[$i];
}
}
// 使用示例
echo FileSizeFormatter::format(1536); // 1.5 KiB
echo FileSizeFormatter::format(1500, FileSizeFormatter::UNITS_SI, 1, 1000); // 1.5 kB
?>
| 維度 | 對數法 | 迭代法 |
|---|---|---|
| 代碼行數 | 極少 | 中等 |
| 可讀性 | 需數學基礎 | 直觀易懂 |
| 擴展性 | 較差 | 優秀 |
| 性能 | 極快(單次運算) | 極快(循環≤6次) |
| 推薦場景 | 一次性腳本、代碼高爾夫 | 通用業務代碼、框架組件 |
實際項目中,建議採用迭代法並封裝為靜態工具方法,兼顧可維護性與性能。