Baytları kilobayt, megabayt, gigabayt olarak biçimlendirin


184

Senaryo: çeşitli dosyaların boyutu bir veritabanında bayt olarak depolanır. Bu boyut bilgilerini kilobayt, megabayt ve gigabayt olarak biçimlendirmenin en iyi yolu nedir? Örneğin, Ubuntu'nun "5,2 MB (5445632 bayt)" olarak görüntülediği bir MP3'üm var. Bunu bir web sayfasında "5,2 MB" olarak nasıl görüntüleyebilirim ve bir megabayttan küçük dosyaların KB olarak ve bir gigabayt ve üzerindeki dosyaların GB olarak görüntülenmesini nasıl sağlayabilirim?


3
Bunu yapan bir işlev oluşturmanız gerektiğine inanıyorum. Numarayı 1024'e bölün ve sonuca bakın. Eğer 1024'ten fazla ise tekrar bölün.
Ivan Nevostruev

Yanıtlar:


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]; 
} 

( Php.net alınan , orada başka birçok örnek vardır, ama ben bu bir en sevdim :-)


8
Eğer kullandıysanız $bytes /= (1 << (10 * $pow))ya da benzeri, ben daha iyi olabilirdi. :-P
Chris Jester-Young

5
İşte böyle: D (kişisel olarak, bitsel aritmetiği sevmiyorum, çünkü buna alışkın olmadığınızı anlamak zor ...)
Leo

3
@ Justin, çünkü 9287695/1024/1024 gerçekten 8.857 :)
Mahn

30
Aslında, bu kadar KiB, MiB, GiBve TiBsen bölerek beri 1024. Eğer bölerseniz 1000o olmadan olurdu i.
Devator

8
Uncomment one of the following alternatives5 dakika fark etmediğim bir şeydi ...
Arnis Juraga

211

Bu, Chris Jester-Young'ın php.net ve hassas bir argümanla birlikte gördüğüm en temiz uygulaması.

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
2 hatası var - (en az küçük) dosya boyutuna 1 ekleyin - 0 ile çalışmıyor (dönüş NAN)
maazza

Güzel bir. Bunun tersi bir versiyonu var mı?
Luke

3
lil rüya : $suffixes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); Yottabyte sabit disk istiyorum! :-P
SpYk3HH

1
i işe almak için bir çift için $ boyutu döküm gerekiyordu. benim için işe yarayan heres: işlev formatBytes ($ size, $ duyarlık = 2) {$ base = log (floatval ($ size)) / log (1024); $ sonekleri = dizi ('', 'k', 'M', 'G', 'T'); dönüş turu (pow (1024, $ base - floor ($ base)), $ duyarlık). $ ekleri [kat ($ baz)]; }
Christopher Gray

formatBytes(259748192, 3)döner 259748192 MBdoğru değil
Ayaklı

97

pseudocode:

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

Microsoft ve Apple 1024 kullanır, bu sizin kullanım durumunuza bağlıdır.
Parsa Yazdani

15

Bu Kohana'nın uygulamasıdır, kullanabilirsiniz:

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]);
}

1024 ila 1000 güç arasında bir seçeneğe sahip olmaları iyi. Ancak bu uygulama gerçekten tuhaf. $force_unitve $siaynı şeyi yapıyor gibi görünüyor. İçinde "i" bulunan herhangi bir dizeyi de geçebilirsiniz $force_unit, çünkü konumu test ederler. Ondalık biçimlendirme de fazladır.
Gus Neves

14

Sadece kb için 1024, mb için 1024 ^ 2 ve GB için 1024 ^ 3'e bölün. Kadar basit.


8

Sadece benim alternatifim, kısa ve temiz:

/**
 * @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];
}

veya daha aptalca ve etkili:

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

kısa kod istiyorsanız bu işlevi kullanı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

Bu soruyu cevaplamak için biraz geç olduğunu biliyorum, ama daha fazla veri birini öldürmeyecek. İşte çok hızlı bir fonksiyon:

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';
}

DÜZENLEME: Mesajımı camomileCase tarafından önerilen düzeltmeyi içerecek şekilde güncelledim:

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 $ gibi küçük değerler için çift B (BB) elde edersiniz, çünkü etrafınızdaki bir çalışma "$ S = 'kMGTPEZY'" yapabilir ve "@ $ S [$ F]" do "@ $ S [$ F-1]".
camomileCase

@camomileCase İki buçuk yıl sonra cevabımı güncelledim. Teşekkürler.
David Bélanger

4

Basit fonksiyon

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

Esnek çözüm:

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

    $o = [
        'binary' => false,
        'decimalPlaces' => 2,
        'decimalSeparator' => '.',
        'thausandsSeparator' => '',
        'maxThreshold' => false, // or thresholds key
        'suffix' => [
            '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['suffix']['bytes'])
        : (
            number_format(
                $size / pow($base, $exp),
                $o['decimalPlaces'],
                $o['decimalSeparator'],
                $o['thausandsSeparator']
            ) .
            str_replace(
                '{threshold}',
                $o['suffix']['thresholds'][$exp],
                $o['suffix'][$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

Aşağıdaki işlevi başardım,

    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
Dikkat: K Kelvin için ve k kilo için.
ZeWaren

2

Benim yaklaşımım

    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

Neden diğerleri kadar karmaşık hale getirmeniz gerektiğini bilmiyorum.

Aşağıdaki kodu anlamak çok daha basittir ve log işlevini kullanan diğer çözümlerden yaklaşık% 25 daha hızlıdır (işlev, farklı parametrelerle 20 Mio. kez olarak adlandırılır)

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

Bu son PHP ile çalışır

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üm bunlar, PHP.net'ten 2010'da ana cevaplayıcı tarafından sadece 8 yıl sonra yapılan bir örneğin aynısı kopyalandı .
JakeGould

2

Ben tüm girdi byte dönüştürmek ve böylece gerekli herhangi bir çıkış dönüştürme yaptım. Ayrıca, temel 1000 veya 1024 almak için yardımcı bir işlev kullandım, ancak popüler tipte 1024 kullanmaya karar vermek için esnek bıraktım (MiB yerine MB gibi 'i' olmadan).

    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

bunu dene ;)

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];
}

Sadece işlevi çağırın

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

1

Biraz eski olsa da, bu kütüphane test edilmiş ve sağlam bir dönüşüm API'sı sunar:

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

Kurulduktan sonra:

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

// Output: "1.00KiB"

Ve diğer yöne dönüştürmek için:

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

// Output: "1024"

Temel dönüşümün ötesinde toplama, çıkarma, karşılaştırma vb. Yöntemler sunar.

Bu kütüphaneye bağlı değilim.


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

Drupal format_size işlevinin basitleştirilmiş uygulaması :

/**
 * 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

Biraz geç oldu ama kabul edilen cevabın biraz daha hızlı bir versiyonu aşağıda:

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];
}

İki log-e işlemi yerine tek bir log-2 işlemi gerçekleştirmesi nedeniyle daha verimlidir.

Ancak, aşağıdaki daha belirgin çözümü yapmak daha hızlıdır:

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];
}

Bunun nedeni, indeksin uygun birimdeki bayt sayısının değeriyle aynı zamanda hesaplanmasıdır. Bu, yürütme süresini yaklaşık% 35 oranında azalttı (% 55 hız artışı).


0

Base 1024 (binary) veya base 1000 (ondalık) 'a çevirebilen ve ayrıca bc kütüphanesinin kullanımından dolayı inanılmaz derecede büyük sayılarla çalışan başka bir yoğun uygulama:

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';
}

Sadece küçük bir yan not; dize değerleri bcpow()değilse $baseve TypeError istisnası atar $i. PHP 7.0.11 sürümünde test edilmiştir.
David Cery

Teşekkürler! Dize tekeri ekledim ve bir ofset hatasını düzelttim :)
Christian

0

Ben kullandığım iki gönderen kodu (Bu konudaki John Himmelman kodunu kullanarak ve Eugene Kuzmenko kodunu kullanarak) bir örgü eklemek olacağını düşündüm .

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
    }
}

Bu, $valuebayt içine biçimlendirmek için Eugene kodunu kullanır (Verilerimi MB olarak tutarım, bu yüzden verilerimi dönüştürür: 10485760 MBiçine 10995116277760) - daha sonra uygun görüntü değerine dönüştürmek için John kodunu kullanır ( 10995116277760içine 10 TB).

Bu gerçekten yararlı buldum - bu yüzden iki gönderen için teşekkürler!


0

İnsan dosya boyutunu almak için son derece basit bir işlev.

Orijinal kaynak: http://php.net/manual/de/function.filesize.php#106569

Kodu kopyala / yapıştır:

<?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

İnsan tarafından okunabilen bellek boyutunu farklı boyutlara dönüştüren kendi işlevimi geliştirdim.

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

Bu işlev "Megabyte, MB, Mb, mb, m, kilobayt, K, KB, b, Terabyte, T ...." gibi herhangi bir bellek boyutu kısaltmasını kabul eder, bu nedenle yazım hatası güvenlidir.


0

Leo'nun cevabına dayandır , ekle

  • Negatif destek
  • Destek 0 <değer <1 (Örn: 0.2, günlük (değer) = negatif sayıya neden olur)

Maksimum birimi Mega olarak istiyorsanız, olarak değiştirin $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];
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.