Format des octets en kilo-octets, mégaoctets, gigaoctets

Scénario: la taille des différents fichiers est stockée dans une base de données sous forme d'octets. Quelle est la meilleure façon de formater cette information de taille en kilo-octets, mégaoctets et gigaoctets? Par exemple, j'ai un MP3 Qu'Ubuntu affiche comme "5.2 MB (5445632 octets)". Comment afficherais-je cela sur une page web en tant que "5.2 MB" et avoir des fichiers de moins d'un mégaoctet en Ko et des fichiers d'un gigaoctet et plus en Go?

146
php
demandé sur Prix 2010-03-24 21:34:55

23 réponses

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

(tiré de php.net , Il y a beaucoup d'autres exemples là-bas, mais j'aime celui-ci le mieux: -)

266
répondu Leo 2010-03-24 18:49:07

C'est la mise en œuvre de Chris Jester-Young, la plus propre que j'ai jamais vue, combinée avec php.net et un argument de précision.

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
183
répondu John Himmelman 2016-02-15 13:38:17

Pseudo-code:

$base = log($size) / log(1024);
$suffix = array("", "k", "M", "G", "T")[floor($base)];
return pow(1024, $base - floor($base)) . $suffix;
94
répondu Chris Jester-Young 2010-03-24 18:39:26

C'est l'implémentation de Kohana, vous pouvez l'utiliser:

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]);
}
13
répondu ryeguy 2010-03-24 18:38:16

Il suffit de le diviser par 1024 pour kb, 1024^2 pour mb et 1024^3 Pour GB. Aussi simple que cela.

12
répondu Vonder 2010-03-24 18:37:22

Utilisez cette fonction si vous voulez un code Court

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
7
répondu Yanni 2012-08-21 10:19:23

Juste mon alternative, courte et propre:

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

Ou, plus stupide et efficace:

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";
}
6
répondu guari 2014-04-11 11:05:53

Je sais qu'il est peut-être un peu tard pour répondre à cette question mais, plus de données ne va pas tuer quelqu'un. Voici une fonction très rapide:

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: j'ai mis à jour mon post pour inclure le correctif proposé par 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';
}
5
répondu David Bélanger 2016-12-14 14:05:31

Fonction Simple

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
2
répondu SebHallin 2017-06-15 06:00:53

J'ai réussi avec la fonction suivante,

    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];
    }
1
répondu Janith Chinthana 2013-08-18 05:16:29

Mon approche

    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];
  }
}
1
répondu user24087 2014-04-24 07:34:12
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
répondu Kerem Çakır 2015-05-29 11:47:59

Je ne sais pas pourquoi vous devriez le rendre aussi compliqué que les autres.

Le code suivant est beaucoup plus simple à comprendre et environ 25% plus rapide que les autres solutions qui utilisent la fonction log (appelée la fonction 20 Mio. avec différents paramètres)

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];
}
1
répondu ZettiCaletti 2017-04-22 01:00:21

Essayez ceci ;)

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);
0
répondu Yahia Mgarrech 2013-08-24 12:25:49
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
répondu mooky 2014-08-17 08:12:49

Voici une implémentation simplifiée de la fonction Drupal format_size :

/**
 * 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
répondu ya.teck 2015-01-19 14:06:31

C'est un peu tard mais une version légèrement plus rapide de la réponse acceptée est ci-dessous:

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

C'est plus efficace, en raison de l'exécution d'une seule opération log-2 au lieu de deux opérations log-E.

Il est en fait plus rapide de faire la solution la plus évidente ci-dessous, cependant:

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

C'est parce que l'index est calculé en même temps que la valeur du nombre d'octets dans l'unité appropriée. Cela réduit le temps d'exécution d'environ 35% (une augmentation de la vitesse de 55%).

0
répondu user3690595 2015-09-18 10:48:26

Une autre implémentation condensée qui peut se traduire en base 1024 (binaire) ou en base 1000 (décimale) et fonctionne également avec des nombres incroyablement grands d'où l'utilisation de la bibliothèque 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';
}
0
répondu Christian 2017-01-06 21:52:38

J'ai pensé que j'ajouterais un maillage de code de deux submitters (en utilisant le code de John Himmelman, qui est dans ce fil, et en utilisant le code deEugene Kuzmenko ) que j'utilise.

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

Cela utilise le code D'Eugene pour formater le $value en octets (je garde mes données en Mo, donc il convertit mes données: 10485760 MB en 10995116277760) - il utilise ensuite le code de John pour le convertir en la valeur d'affichage appropriée (10995116277760 en 10 TB).

J'ai trouvé cela vraiment utile-donc mes remerciements aux deux auteurs!

0
répondu EML 2017-07-17 20:55:51

Fonction extrêmement simple pour obtenir la taille du fichier humain.

Source Originale: http://php.net/manual/de/function.filesize.php#106569

Copier/coller le code:

<?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
répondu John Erck 2017-10-19 15:11:59

J'ai développé ma propre fonction qui convertit la taille de la mémoire lisible par l'homme en différentes tailles.

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

Cette fonction accepte toute abréviation de taille de mémoire comme " mégaoctet, MB, Mb, mb, m, kilooctet, K, KB, b, téraoctet, T...."donc, c'est de la faute de frappe coffre-fort.

0
répondu Juan Lago 2018-01-16 22:20:07
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];
}

Appelez simplement la fonction

echo convertToReadableSize(1024); // Outputs '1KB'
echo convertToReadableSize(1024 * 1024); // Outputs '1MB'
0
répondu Madushanka Sampath 2018-01-26 11:39:31

Base sur la réponse de Leo , Ajouter

  • Support Pour négatif
  • Soutien 0

Si vous voulez que l'unité max soit méga, passez à $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];
}
0
répondu Steely Wing 2018-08-30 04:10:51