Định dạng byte thành kilobyte, megabyte, gigabyte


184

Kịch bản: kích thước của các tệp khác nhau được lưu trữ trong cơ sở dữ liệu dưới dạng byte. Cách tốt nhất để định dạng thông tin kích thước này thành kilobyte, megabyte và gigabyte là gì? Chẳng hạn, tôi có một bản MP3 mà Ubuntu hiển thị là "5,2 MB (5445632 byte)". Làm cách nào để hiển thị thông tin này trên trang web là "5,2 MB" VÀ có các tệp có ít hơn một megabyte hiển thị dưới dạng KB và các tệp một gigabyte trở lên hiển thị dưới dạng GB?


3
Tôi tin rằng bạn nên tạo ra một chức năng làm điều này. Chỉ cần chia số cho 1024 và nhìn vào kết quả. Nếu nhiều hơn 1024 thì chia lại.
Ivan Nevostruev

Câu trả lời:


319
function formatBytes($bytes, $precision = 2) { 
    $units = array('B', 'KB', 'MB', 'GB', 'TB'); 

    $bytes = max($bytes, 0); 
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); 
    $pow = min($pow, count($units) - 1); 

    // Uncomment one of the following alternatives
    // $bytes /= pow(1024, $pow);
    // $bytes /= (1 << (10 * $pow)); 

    return round($bytes, $precision) . ' ' . $units[$pow]; 
} 

(Lấy từ php.net , có nhiều ví dụ khác ở đó, nhưng tôi thích cái này nhất :-)


8
Nếu bạn sử dụng $bytes /= (1 << (10 * $pow))hoặc tương tự, tôi có thể thích nó tốt hơn. :-P
Chris Jester-Young

5
Ở đó bạn đi: D (cá nhân, tôi không thích số học bitwise, bởi vì thật khó hiểu nếu bạn không quen với nó ...)
Leo

3
@Justin đó là vì 9287695/1024/1024 thực sự là 8,857 :)
Mahn

30
Trên thực tế, đó là KiB, MiB, GiBTiBvì bạn đang chia 1024. Nếu bạn chia cho 1000nó sẽ không có i.
Devator

7
Uncomment one of the following alternativeslà điều mà tôi đã không nhận thấy trong 5 phút ...
Arnis Juraga

210

Đây là cách triển khai của Chris Jester-Young, rõ ràng nhất tôi từng thấy, kết hợp với php.net và một đối số chính xác.

function formatBytes($size, $precision = 2)
{
    $base = log($size, 1024);
    $suffixes = array('', 'K', 'M', 'G', 'T');   

    return round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)];
}

echo formatBytes(24962496);
// 23.81M

echo formatBytes(24962496, 0);
// 24M

echo formatBytes(24962496, 4);
// 23.8061M

8
nó có 2 lỗi - thêm 1 đến (ít nhất là nhỏ) kích thước tệp - không hoạt động với 0 (trả về NAN)
maazza

Đẹp một. Có một phiên bản này theo cách khác xung quanh?
Luke

3
Một giấc mơ lil : $suffixes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); Tôi muốn có một ổ cứng Yottabyte! :-P
SpYk3HH

1
tôi đã phải bỏ kích thước $ thành gấp đôi để làm cho nó hoạt động. Đây là những gì làm việc cho tôi: function formatBytes ($ size, $ precision = 2) {$ base = log (floatval ($ size)) / log (1024); $ hậu tố = mảng ('', 'k', 'M', 'G', 'T'); vòng quay lại (pow (1024, $ base - floor ($ base)), $ chính xác). $ hậu tố [sàn ($ cơ sở)]; }
Christopher Gray

formatBytes(259748192, 3)trả lại 259748192 MBkhông đúng
Lật

97

Mã giả:

$base = log($size) / log(1024);
$suffix = array("", "k", "M", "G", "T")[floor($base)];
return pow(1024, $base - floor($base)) . $suffix;

Microsoft và Apple sử dụng 1024, nó phụ thuộc vào trường hợp sử dụng của bạn.
Parsa Yazdani

15

Đây là triển khai của Kohana , bạn có thể sử dụng nó:

public static function bytes($bytes, $force_unit = NULL, $format = NULL, $si = TRUE)
{
    // Format string
    $format = ($format === NULL) ? '%01.2f %s' : (string) $format;

    // IEC prefixes (binary)
    if ($si == FALSE OR strpos($force_unit, 'i') !== FALSE)
    {
        $units = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB');
        $mod   = 1024;
    }
    // SI prefixes (decimal)
    else
    {
        $units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB');
        $mod   = 1000;
    }

    // Determine unit to use
    if (($power = array_search((string) $force_unit, $units)) === FALSE)
    {
        $power = ($bytes > 0) ? floor(log($bytes, $mod)) : 0;
    }

    return sprintf($format, $bytes / pow($mod, $power), $units[$power]);
}

Ý tưởng của họ về việc có một tùy chọn giữa 1024 và 1000 sức mạnh là tốt. Nhưng việc thực hiện này thực sự kỳ lạ. $force_unit$sidường như làm điều tương tự. Bạn cũng có thể chuyển bất kỳ chuỗi nào có chữ "i" trong đó $force_unit, vì chúng kiểm tra vị trí. Các định dạng thập phân cũng là quá mức cần thiết.
Gus Neves

14

Chỉ cần chia nó cho 1024 cho kb, 1024 ^ 2 cho mb và 1024 ^ 3 cho GB. Đơn giản vậy thôi.


8

Chỉ cần thay thế của tôi, ngắn và sạch sẽ:

/**
 * @param int $bytes Number of bytes (eg. 25907)
 * @param int $precision [optional] Number of digits after the decimal point (eg. 1)
 * @return string Value converted with unit (eg. 25.3KB)
 */
function formatBytes($bytes, $precision = 2) {
    $unit = ["B", "KB", "MB", "GB"];
    $exp = floor(log($bytes, 1024)) | 0;
    return round($bytes / (pow(1024, $exp)), $precision).$unit[$exp];
}

hoặc, ngu ngốc và hiệu quả hơn:

function formatBytes($bytes, $precision = 2) {
    if ($bytes > pow(1024,3)) return round($bytes / pow(1024,3), $precision)."GB";
    else if ($bytes > pow(1024,2)) return round($bytes / pow(1024,2), $precision)."MB";
    else if ($bytes > 1024) return round($bytes / 1024, $precision)."KB";
    else return ($bytes)."B";
}

7

sử dụng chức năng này nếu bạn muốn một mã ngắn

bcdiv ()

$size = 11485760;
echo bcdiv($size, 1048576, 0); // return: 10

echo bcdiv($size, 1048576, 2); // return: 10,9

echo bcdiv($size, 1048576, 2); // return: 10,95

echo bcdiv($size, 1048576, 3); // return: 10,953

6

Tôi biết có lẽ hơi muộn để trả lời câu hỏi này, nhưng, nhiều dữ liệu sẽ không giết chết ai đó. Đây là một chức năng rất nhanh:

function format_filesize($B, $D=2){
    $S = 'BkMGTPEZY';
    $F = floor((strlen($B) - 1) / 3);
    return sprintf("%.{$D}f", $B/pow(1024, $F)).' '.@$S[$F].'B';
}

EDIT: Tôi đã cập nhật bài đăng của mình để bao gồm bản sửa lỗi được đề xuất bởi camomileCase:

function format_filesize($B, $D=2){
    $S = 'kMGTPEZY';
    $F = floor((strlen($B) - 1) / 3);
    return sprintf("%.{$D}f", $B/pow(1024, $F)).' '.@$S[$F-1].'B';
}

1
Bạn nhận được gấp đôi B (BB) cho các giá trị nhỏ $ B, vì công việc xung quanh bạn có thể tạo ra "$ S = 'kMGTPEZY'" và thay vì "@ $ S [$ F]" do "@ $ S [$ F-1] ".
camomileCase

@camomileCase Hai năm rưỡi sau - Tôi đã cập nhật câu trả lời của mình. Cảm ơn.
David Bélanger

4

Chức năng đơn giản

function formatBytes($size, $precision = 0){
    $unit = ['Byte','KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];

    for($i = 0; $size >= 1024 && $i < count($unit)-1; $i++){
        $size /= 1024;
    }

    return round($size, $precision).' '.$unit[$i];
}

echo formatBytes('1876144', 2);
//returns 1.79 MiB

3

Giải pháp linh hoạt:

function size($size, array $options=null) {

    $o = [
        'binary' => false,
        'decimalPlaces' => 2,
        'decimalSeparator' => '.',
        'thausandsSeparator' => '',
        'maxThreshold' => false, // or thresholds key
        'sufix' => [
            'thresholds' => ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
            'decimal' => ' {threshold}B',
            'binary' => ' {threshold}iB',
            'bytes' => ' B'
        ]
    ];

    if ($options !== null)
        $o = array_replace_recursive($o, $options);

    $base = $o['binary'] ? 1024 : 1000;
    $exp = $size ? floor(log($size) / log($base)) : 0;

    if (($o['maxThreshold'] !== false) &&
        ($o['maxThreshold'] < $exp)
    )
        $exp = $o['maxThreshold'];

    return !$exp
        ? (round($size) . $o['sufix']['bytes'])
        : (
            number_format(
                $size / pow($base, $exp),
                $o['decimalPlaces'],
                $o['decimalSeparator'],
                $o['thausandsSeparator']
            ) .
            str_replace(
                '{threshold}',
                $o['sufix']['thresholds'][$exp],
                $o['sufix'][$o['binary'] ? 'binary' : 'decimal']
            )
        );
}

var_dump(size(disk_free_space('/')));
// string(8) "14.63 GB"
var_dump(size(disk_free_space('/'), ['binary' => true]));
// string(9) "13.63 GiB"
var_dump(size(disk_free_space('/'), ['maxThreshold' => 2]));
// string(11) "14631.90 MB"
var_dump(size(disk_free_space('/'), ['binary' => true, 'maxThreshold' => 2]));
// string(12) "13954.07 MiB"

2

Tôi đã thành công với chức năng sau đây,

    function format_size($size) {
        $mod = 1024;
        $units = explode(' ','B KB MB GB TB PB');
        for ($i = 0; $size > $mod; $i++) {
            $size /= $mod;
        }
        return round($size, 2) . ' ' . $units[$i];
    }

2
Coi chừng: K là cho Kelvin và k là kilôgam.
ZeWaren

2

Cách tiếp cận của tôi

    function file_format_size($bytes, $decimals = 2) {
  $unit_list = array('B', 'KB', 'MB', 'GB', 'PB');

  if ($bytes == 0) {
    return $bytes . ' ' . $unit_list[0];
  }

  $unit_count = count($unit_list);
  for ($i = $unit_count - 1; $i >= 0; $i--) {
    $power = $i * 10;
    if (($bytes >> $power) >= 1)
      return round($bytes / (1 << $power), $decimals) . ' ' . $unit_list[$i];
  }
}

2

Tôi không biết tại sao bạn nên làm cho nó phức tạp như những người khác.

Đoạn mã sau đơn giản hơn để hiểu và nhanh hơn khoảng 25% so với các giải pháp khác sử dụng hàm nhật ký (được gọi là hàm 20 Mio. lần với các tham số khác nhau)

function formatBytes($bytes, $precision = 2) {
    $units = ['Byte', 'Kilobyte', 'Megabyte', 'Gigabyte', 'Terabyte'];
    $i = 0;

    while($bytes > 1024) {
        $bytes /= 1024;
        $i++;
    }
    return round($bytes, $precision) . ' ' . $units[$i];
}

2

Tôi đã làm điều này để chuyển đổi tất cả đầu vào thành byte và do đó chuyển đổi sang bất kỳ đầu ra nào cần thiết. Ngoài ra, tôi đã sử dụng một chức năng phụ trợ để lấy cơ sở 1000 hoặc 1024, nhưng để nó linh hoạt để quyết định sử dụng 1024 trên loại phổ biến (không có 'i', như MB thay vì MiB).

    public function converte_binario($size=0,$format_in='B',$format_out='MB',$force_in_1024=false,$force_out_1024=false,$precisao=5,$return_format=true,$decimal=',',$centena=''){
    $out = false;

    if( (is_numeric($size)) && ($size>0)){
        $in_data = $this->converte_binario_aux($format_in,$force_in_1024);
        $out_data = $this->converte_binario_aux($format_out,$force_out_1024);

        // se formato de entrada e saída foram encontrados
        if( ((isset($in_data['sucesso'])) && ($in_data['sucesso']==true)) && ((isset($out_data['sucesso'])) && ($out_data['sucesso']==true))){
            // converte formato de entrada para bytes.
            $size_bytes_in = $size * (pow($in_data['base'], $in_data['pot']));
            $size_byte_out = (pow($out_data['base'], $out_data['pot']));
            // transforma bytes na unidade de destino
            $out = number_format($size_bytes_in / $size_byte_out,$precisao,$decimal,$centena);
            if($return_format){
                $out .= $format_out;
            }
        }
    }
    return $out;
}

public function converte_binario_aux($format=false,$force_1024=false){
    $out = [];
    $out['sucesso'] = false;
    $out['base'] = 0;
    $out['pot'] = 0;
    if((is_string($format) && (strlen($format)>0))){
        $format = trim(strtolower($format));
        $units_1000 = ['b','kb' ,'mb' ,'gb' ,'tb' ,'pb' ,'eb' ,'zb' ,'yb' ];
        $units_1024 = ['b','kib','mib','gib','tib','pib','eib','zib','yib'];
        $pot = array_search($format,$units_1000);
        if( (is_numeric($pot)) && ($pot>=0)){
            $out['pot'] = $pot;
            $out['base'] = 1000;
            $out['sucesso'] = true;
        }
        else{
            $pot = array_search($format,$units_1024);
            if( (is_numeric($pot)) && ($pot>=0)){
                $out['pot'] = $pot;
                $out['base'] = 1024;
                $out['sucesso'] = true;
            }
        }
        if($force_1024){
            $out['base'] = 1024;
        }
    }
    return $out;
}

1

thử cái này ;)

function bytesToSize($bytes) {
                $sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
                if ($bytes == 0) return 'n/a';
                $i = intval(floor(log($bytes) / log(1024)));
                if ($i == 0) return $bytes . ' ' . $sizes[$i]; 
                return round(($bytes / pow(1024, $i)),1,PHP_ROUND_HALF_UP). ' ' . $sizes[$i];
            }
echo bytesToSize(10000050300);

1
function changeType($size, $type, $end){
    $arr = ['B', 'KB', 'MB', 'GB', 'TB'];
    $tSayi = array_search($type, $arr);
    $eSayi = array_search($end, $arr);
    $pow = $eSayi - $tSayi;
    return $size * pow(1024 * $pow) . ' ' . $end;
}

echo changeType(500, 'B', 'KB');

1
function convertToReadableSize($size)
{
  $base = log($size) / log(1024);
  $suffix = array("B", "KB", "MB", "GB", "TB");
  $f_base = floor($base);
  return round(pow(1024, $base - floor($base)), 1) . $suffix[$f_base];
}

Chỉ cần gọi chức năng

echo convertToReadableSize(1024); // Outputs '1KB'
echo convertToReadableSize(1024 * 1024); // Outputs '1MB'

1

Công việc này với PHP cuối cùng

function formatBytes($bytes, $precision = 2) { 
    $units = array('B', 'KB', 'MB', 'GB', 'TB'); 

    $bytes = max($bytes, 0); 
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); 
    $pow = min($pow, count($units) - 1); 

    $bytes /= pow(1024, $pow); 

    return round($bytes, $precision) . ' ' . $units[$pow]; 
} 

Tất cả những gì đã được thực hiện ở đó là cùng một bản sao chính xác của một ví dụ từ PHP.net, được người trả lời chính thực hiện vào năm 2010 chỉ thực hiện 8 năm sau đó.
JakeGould

1

Mặc dù hơi cũ, thư viện này cung cấp API chuyển đổi được thử nghiệm và mạnh mẽ:

https://github.com/gabrielelana/byte-units

Một lần được cài đặt:

\ByteUnits\Binary::bytes(1024)->format();

// Output: "1.00KiB"

Và để chuyển đổi theo hướng khác:

\ByteUnits\Binary::parse('1KiB')->numberOfBytes();

// Output: "1024"

Ngoài chuyển đổi cơ bản, nó cung cấp các phương thức để cộng, trừ, so sánh, v.v.

Tôi không có cách nào liên kết với thư viện này.


0
function byte_format($size) {
    $bytes = array( ' KB', ' MB', ' GB', ' TB' );
    foreach ($bytes as $val) {
        if (1024 <= $size) {
            $size = $size / 1024;
            continue;
        }
        break;
    }
    return round( $size, 1 ) . $val;
}

0

Dưới đây là đơn giản hóa việc thực hiện chức năng định dạng Drupal :

/**
 * Generates a string representation for the given byte count.
 *
 * @param $size
 *   A size in bytes.
 *
 * @return
 *   A string representation of the size.
 */
function format_size($size) {
  if ($size < 1024) {
    return $size . ' B';
  }
  else {
    $size = $size / 1024;
    $units = ['KB', 'MB', 'GB', 'TB'];
    foreach ($units as $unit) {
      if (round($size, 2) >= 1024) {
        $size = $size / 1024;
      }
      else {
        break;
      }
    }
    return round($size, 2) . ' ' . $unit;
  }
}

0

Hơi muộn một chút nhưng phiên bản nhanh hơn của câu trả lời được chấp nhận ở bên dưới:

function formatBytes($bytes, $precision)
{
    $unit_list = array
    (
        'B',
        'KB',
        'MB',
        'GB',
        'TB',
    );

    $bytes = max($bytes, 0);
    $index = floor(log($bytes, 2) / 10);
    $index = min($index, count($unit_list) - 1);
    $bytes /= pow(1024, $index);

    return round($bytes, $precision) . ' ' . $unit_list[$index];
}

Nó hiệu quả hơn, do thực hiện một thao tác log-2 đơn thay vì hai thao tác log-e.

Tuy nhiên, thực sự nhanh hơn để thực hiện giải pháp rõ ràng hơn dưới đây:

function formatBytes($bytes, $precision)
{
    $unit_list = array
    (
        'B',
        'KB',
        'MB',
        'GB',
        'TB',
    );

    $index_max = count($unit_list) - 1;
    $bytes = max($bytes, 0);

    for ($index = 0; $bytes >= 1024 && $index < $index_max; $index++)
    {
        $bytes /= 1024;
    }

    return round($bytes, $precision) . ' ' . $unit_list[$index];
}

Điều này là do chỉ số được tính toán cùng lúc với giá trị của số byte trong đơn vị thích hợp. Điều này giúp giảm thời gian thực hiện khoảng 35% (tăng tốc độ 55%).


0

Một triển khai cô đọng khác có thể dịch sang cơ sở 1024 (nhị phân) hoặc cơ sở 1000 (thập phân) và cũng hoạt động với số lượng cực lớn do sử dụng thư viện bc:

function renderSize($byte,$precision=2,$mibi=true)
{
    $base = (string)($mibi?1024:1000);
    $labels = array('K','M','G','T','P','E','Z','Y');
    for($i=8;$i>=1;$i--)
        if(bccomp($byte,bcpow($base, $i))>=0)
            return bcdiv($byte,bcpow($base, $i), $precision).' '.$labels[$i-1].($mibi?'iB':'B');
    return $byte.' Byte';
}

Chỉ cần một lưu ý phụ; bcpow()sẽ ném ngoại lệ TypeError nếu $base$ikhông phải là giá trị chuỗi. Đã thử nghiệm trên phiên bản PHP 7.0.11.
David Cery

Cảm ơn! Tôi đã thêm chuỗi caster và sửa lỗi bù :)
Christian

0

Tôi hình dung rằng tôi sẽ thêm một mạng lưới gồm hai mã trình đệ trình (Sử dụng mã của John Himmelman, trong chuỗi này và sử dụng mã của Eugene Kuzmenko ) mà tôi đang sử dụng.

function swissConverter($value, $format = true, $precision = 2) {
    //Below converts value into bytes depending on input (specify mb, for 
    //example)
    $bytes = preg_replace_callback('/^\s*(\d+)\s*(?:([kmgt]?)b?)?\s*$/i', 
    function ($m) {
        switch (strtolower($m[2])) {
          case 't': $m[1] *= 1024;
          case 'g': $m[1] *= 1024;
          case 'm': $m[1] *= 1024;
          case 'k': $m[1] *= 1024;
        }
        return $m[1];
        }, $value);
    if(is_numeric($bytes)) {
        if($format === true) {
            //Below converts bytes into proper formatting (human readable 
            //basically)
            $base = log($bytes, 1024);
            $suffixes = array('', 'KB', 'MB', 'GB', 'TB');   

            return round(pow(1024, $base - floor($base)), $precision) .' '. 
                     $suffixes[floor($base)];
        } else {
            return $bytes;
        }
    } else {
        return NULL; //Change to prefered response
    }
}

Điều này sử dụng mã của Eugene để định dạng $valuethành byte (Tôi giữ dữ liệu của mình bằng MB, do đó, nó chuyển đổi dữ liệu của tôi: 10485760 MBthành 10995116277760) - sau đó sử dụng mã của John để chuyển đổi thành giá trị hiển thị phù hợp ( 10995116277760thành10 TB ).

Tôi đã tìm thấy điều này thực sự hữu ích - vì vậy tôi cảm ơn hai người đệ trình!


0

Chức năng cực kỳ đơn giản để có được kích thước tập tin của con người.

Nguồn gốc: http://php.net/manual/de/feft.filesize.php#106569

Sao chép / dán mã:

<?php
function human_filesize($bytes, $decimals = 2) {
  $sz = 'BKMGTP';
  $factor = floor((strlen($bytes) - 1) / 3);
  return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
?>

0

Tôi đã phát triển chức năng của riêng mình để chuyển đổi kích thước bộ nhớ có thể đọc được của con người thành các kích thước khác nhau.

function convertMemorySize($strval, string $to_unit = 'b')
{
    $strval    = strtolower(str_replace(' ', '', $strval));
    $val       = floatval($strval);
    $to_unit   = strtolower(trim($to_unit))[0];
    $from_unit = str_replace($val, '', $strval);
    $from_unit = empty($from_unit) ? 'b' : trim($from_unit)[0];
    $units     = 'kmgtph';  // (k)ilobyte, (m)egabyte, (g)igabyte and so on...


    // Convert to bytes
    if ($from_unit !== 'b')
        $val *= 1024 ** (strpos($units, $from_unit) + 1);


    // Convert to unit
    if ($to_unit !== 'b')
        $val /= 1024 ** (strpos($units, $to_unit) + 1);


    return $val;
}


convertMemorySize('1024Kb', 'Mb');  // 1
convertMemorySize('1024', 'k')      // 1
convertMemorySize('5.2Mb', 'b')     // 5452595.2
convertMemorySize('10 kilobytes', 'bytes') // 10240
convertMemorySize(2048, 'k')        // By default convert from bytes, result is 2

Hàm này chấp nhận mọi chữ viết tắt kích thước bộ nhớ như "Megabyte, MB, Mb, mb, m, kilobyte, K, KB, b, Terabyte, T ...." vì vậy nó an toàn cho lỗi đánh máy.


0

Dựa trên câu trả lời của Leo , thêm

  • Hỗ trợ tiêu cực
  • Hỗ trợ 0 <value <1 (Ví dụ: 0,2, sẽ gây ra log (value) = số âm)

Nếu bạn muốn đơn vị tối đa thành Mega, hãy đổi thành $units = explode(' ', ' K M');


function formatUnit($value, $precision = 2) {
    $units = explode(' ', ' K M G T P E Z Y');

    if ($value < 0) {
        return '-' . formatUnit(abs($value));
    }

    if ($value < 1) {
        return $value . $units[0];
    }

    $power = min(
        floor(log($value, 1024)),
        count($units) - 1
    );

    return round($value / pow(1024, $power), $precision) . $units[$power];
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.