【问题标题】:human readable file size人类可读的文件大小
【发布时间】:2013-02-17 17:49:36
【问题描述】:
function humanFileSize($size)
{
    if ($size >= 1073741824) {
      $fileSize = round($size / 1024 / 1024 / 1024,1) . 'GB';
    } elseif ($size >= 1048576) {
        $fileSize = round($size / 1024 / 1024,1) . 'MB';
    } elseif($size >= 1024) {
        $fileSize = round($size / 1024,1) . 'KB';
    } else {
        $fileSize = $size . ' bytes';
    }
    return $fileSize;
}

... 效果很好,除了:我无法手动选择需要显示的格式,比如我只想以 MB 显示文件大小。目前如果它在 GB 范围内,它只会以 GB 显示。

另外,如何将小数限制为 2?

【问题讨论】:

    标签: php filesize


    【解决方案1】:

    试试这样的:

    function humanFileSize($size,$unit="") {
      if( (!$unit && $size >= 1<<30) || $unit == "GB")
        return number_format($size/(1<<30),2)."GB";
      if( (!$unit && $size >= 1<<20) || $unit == "MB")
        return number_format($size/(1<<20),2)."MB";
      if( (!$unit && $size >= 1<<10) || $unit == "KB")
        return number_format($size/(1<<10),2)."KB";
      return number_format($size)." bytes";
    }
    

    【讨论】:

    • 应该是$unit == "GB" || !$unit &amp;&amp; $size &gt;= 1&lt;&lt;30
    • @Gumbo 为什么?它有什么不同?实际上,对于像0 这样的非字符串参数,这会破坏它。
    • 您的解决方案要求该值至少为单位大小的 1,即无法像 0.5 GB 那样获得小于 1 的值。在这种情况下,结果以字节为单位显示。
    • @Nimbuz 这可能是因为它假设 1MB == 1000000 字节(实际上是 1024*1024 字节)。
    • @KrzysztofKarski 欢迎您提供反馈,但使用1&lt;&lt;10 代替1024 的原因与使用1&lt;&lt;30 代替1073741824 的原因相同——它传达了更多含义。此外,添加更大的单位是微不足道的,只需添加带有1&lt;&lt;40"TB" 的变体,甚至更多。这个答案的重点不是 100% 完整的解决方案,因此“试试 like this:”文本。
    【解决方案2】:

    你可以修改你的函数来满足你需要强制一个单位(如果给定)和调整精度。

    function humanFileSize($size, $precision = 1, $show = "")
    {
        $b = $size;
        $kb = round($size / 1024, $precision);
        $mb = round($kb / 1024, $precision);
        $gb = round($mb / 1024, $precision);
    
        if($kb == 0 || $show == "B") {
            return $b . " bytes";
        } else if($mb == 0 || $show == "KB") {
            return $kb . "KB";
        } else if($gb == 0 || $show == "MB") {
            return $mb . "MB";
        } else {
            return $gb . "GB";
        }
    }
    
    //Test with different values
    echo humanFileSize(1038) . "<br />";    
    echo humanFileSize(103053, 0) . "<br />";
    echo humanFileSize(103053) . "<br />";
    echo humanFileSize(1030544553) . "<br />";
    echo humanFileSize(1030534053405, 2, "GB") . "<br />";  ;
    

    【讨论】:

      【解决方案3】:
      function getHumanReadableSize($size, $unit = null, $decemals = 2) {
          $byteUnits = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
          if (!is_null($unit) && !in_array($unit, $byteUnits)) {
              $unit = null;
          }
          $extent = 1;
          foreach ($byteUnits as $rank) {
              if ((is_null($unit) && ($size < $extent <<= 10)) || ($rank == $unit)) {
                  break;
              }
          }
          return number_format($size / ($extent >> 10), $decemals) . $rank;
      }
      

      如果 php 版本低于 5.4 使用 $byteUnits = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');

      【讨论】:

        【解决方案4】:

        我想要一个像 Windows 一样返回文件大小的函数,但令人惊讶的是我根本找不到。更糟糕的是,这里和其他地方的一些错误假设 1KB = 1000B。

        所以我编码了一个!加上两个辅助函数。他们在这里:

        // Returns a size in a human-readable form from a byte count.
        function humanSize($bytes)
        {
            if ($bytes < 1024) return "$bytes Bytes";
        
            $units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        
            foreach ($units as $i => $unit)
            {
                // The reason for this threshold is to avoid e.g., "1000 KB",
                // instead jumping from e.g., "999 KB" to "0.97 MB".
                $multiplier = pow(1024, $i + 1);
                $threshold = $multiplier * 1000;
        
                if ($bytes < $threshold)
                {
                    $size = formatToMinimumDigits($bytes / $multiplier, false);
                    return "$size $unit";
                }
            }
        }
        
        // Efficiently calculates how many digits the integer portion of a number has.
        function digits($number)
        {
            // Yes, I could convert to string and count the characters,
            // but this is faster and cooler.
            $log = log10($number);
            if ($log < 0) return 1;
            return floor($log) + 1;
        }
        
        // Formats a number to a minimum amount of digits.
        // In other words, makes sure that a number has at least $digits on it, even if
        // that means introducing redundant decimal zeroes at the end, or rounding the
        // ones present exceeding the $digits count when combined with the integers.
        // For example:
        //     formatToMinimumDigits(10)           // 10.0
        //     formatToMinimumDigits(1.1)          // 1.10
        //     formatToMinimumDigits(12.34)        // 12.3
        //     formatToMinimumDigits(1.234)        // 1.23
        //     formatToMinimumDigits(1.203)        // 1.20
        //     formatToMinimumDigits(123.4)        // 123
        //     formatToMinimumDigits(100)          // 100
        //     formatToMinimumDigits(1000)         // 1000
        //     formatToMinimumDigits(1)            // 1.00
        //     formatToMinimumDigits(1.002)        // 1.00
        //     formatToMinimumDigits(1.005)        // 1.01
        //     formatToMinimumDigits(1.005, false) // 1.00
        // This is primarily useful for generating human-friendly numbers.
        function formatToMinimumDigits($value, $round = true, $digits = 3)
        {
            $integers = floor($value);
        
            $decimalsNeeded = $digits - digits($integers);
        
            if ($decimalsNeeded < 1)
            {
                return $integers;
            }
            else
            {
                if ($round)
                {
                    // This relies on implicit type casting of float to string.
                    $parts = explode('.', round($value, $decimalsNeeded));
                    // We re-declare the integers because they may change
                    // after we round the number.
                    $integers = $parts[0];
                }
                else
                {
                    // Again, implicit type cast to string.
                    $parts = explode('.', $value);
                }
        
                // And because of the implicit type cast, we must guard against
                // 1.00 becoming 1, thus not exploding the second half of it.
                $decimals = isset($parts[1]) ? $parts[1] : '0';
                $joined = "$integers.$decimals".str_repeat('0', $digits);
                return substr($joined, 0, $digits + 1);
            }
        }
        

        使用就像humanSize(123456789)一样简单。

        【讨论】:

          【解决方案5】:

          Jeffrey Sambells 有一个很好的例子:

          function human_filesize($bytes, $dec = 2) 
          {
              $size   = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
              $factor = floor((strlen($bytes) - 1) / 3);
          
              return sprintf("%.{$dec}f", $bytes / pow(1024, $factor)) . @$size[$factor];
          }
          
          print human_filesize(filesize('example.zip'));
          

          【讨论】:

          • 很好,但我会添加if($factor==0) $dec=0;
          • 不准确,4,281,016 字节为 4.08 MB,而 google 则为 4.28102 MB
          • 谷歌没有错。 1MB = 1000000B。 1MiB = 1048576B。他们只是遵循最新的 IEC 单位标准:en.wikipedia.org/wiki/Binary_prefix
          • 返回线也可以使用:return sprintf("%.{$dec}f %s", $bytes / (1024 ** $factor), $size[$factor]); 干净一点。
          • @maki10 谢谢!我写pow() 已经有10 年了,这是我第一次看到** 运算符。令人难以置信,因为它从 5.6 版开始可用(:我也同意 sprintf 快捷方式。您是否已将其作为编辑提交?如果没有,请提交。
          【解决方案6】:

          我正在使用这种方法:

          function byteConvert($bytes)
          {
              if ($bytes == 0)
                  return "0.00 B";
          
              $s = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
              $e = floor(log($bytes, 1024));
          
              return round($bytes/pow(1024, $e), 2).$s[$e];
          }
          

          在 o(1) 中效果很好。

          【讨论】:

            【解决方案7】:

            这是一个管理到 Yottabyte 的工作函数:

            function DisplayFileSize($size, $unit = false, $precision = 2){
            
            $b = $size;
            $kb = round($size / 1024, $precision);
            $mb = round($kb / 1024, $precision);
            $gb = round($mb / 1024, $precision);
            $tb = round($gb / 1024, $precision);
            $pb = round($tb / 1024, $precision);
            $eb = round($pb / 1024, $precision);
            $zb = round($eb / 1024, $precision);
            $yb = round($zb / 1024, $precision);
            
            if((!$unit && floor($kb) == 0) || $unit == "b") {
                return array("value" => FormatNumber($b), "unit" => "bytes");
            } else if((!$unit && floor($mb) == 0) || $unit == "kb") {
                return array("value" => FormatNumber($kb, 2), "unit" => "Kb");
            } else if((!$unit && floor($gb) == 0) || $unit == "mb") {
                return array("value" => FormatNumber($mb, 2), "unit" => "Mb");
             } else if((!$unit && floor($tb) == 0) || $unit == "gb") {
                 return array("value" => FormatNumber($gb, 2), "unit" => "Gb");
             } else if((!$unit && floor($pb) == 0) || $unit == "tb") {
                 return array("value" => FormatNumber($tb, 2), "unit" => "Tb");
             } else if((!$unit && floor($eb) == 0) || $unit == "pb") {
                return array("value" => FormatNumber($pb, 2), "unit" => "Pb");
             } else if((!$unit && floor($zb) == 0) || $unit == "eb") {
                 return array("value" => FormatNumber($eb, 2), "unit" => "Eb");
             } else if((!$unit && floor($yb) == 0) || $unit == "zb") {
                 return array("value" => FormatNumber($zb, 2), "unit" => "Zb");
            } else {
                return array("value" => FormatNumber($yb, 2), "unit" => "Yb");
            }
            

            }

            【讨论】:

              【解决方案8】:

              要扩展 Vaidas 的答案,您应该按照以下方式来考虑新的 IEC 标准:

              function human_readable_bytes($bytes, $decimals = 2, $system = 'binary')
              {
                  $mod = ($system === 'binary') ? 1024 : 1000;
              
                  $units = array(
                      'binary' => array(
                          'B',
                          'KiB',
                          'MiB',
                          'GiB',
                          'TiB',
                          'PiB',
                          'EiB',
                          'ZiB',
                          'YiB',
                      ),
                      'metric' => array(
                          'B',
                          'kB',
                          'MB',
                          'GB',
                          'TB',
                          'PB',
                          'EB',
                          'ZB',
                          'YB',
                      ),
                  );
              
                  $factor = floor((strlen($bytes) - 1) / 3);
              
                  return sprintf("%.{$decimals}f%s", $bytes / pow($mod, $factor), $units[$system][$factor]);
              }
              

              从技术上讲,根据存储设备的规格等,您应该默认使用公制(这就是为什么 Google 转换器将 kB -> MB 显示为 mod 1000 而不是 1024)。

              【讨论】:

              • $size 应该是 $bytes
              • 已修复。感谢您的关注。
              【解决方案9】:

              我使用的一种非常短的 3 行方法 (1024 = 1KB) 并支持从 KB 到 YB,如下所示:

              <?php 
              
              /**
               * Converts a long string of bytes into a readable format e.g KB, MB, GB, TB, YB
               * 
               * @param {Int} num The number of bytes.
               */
              function readableBytes($bytes) {
                  $i = floor(log($bytes) / log(1024));
              
                  $sizes = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
              
                  return sprintf('%.02F', $bytes / pow(1024, $i)) * 1 . ' ' . $sizes[$i];
              }
              
              // "1000 B"
              echo readableBytes(1000);
              
              // "9.42 MB"
              echo readableBytes(9874321);
              
              // "9.31 GB"
              // The number of bytes as a string is accepted as well
              echo readableBytes("10000000000");
              
              // "648.37 TB"
              echo readableBytes(712893712304234);
              
              // "5.52 PB"
              echo readableBytes(6212893712323224);
              

              More info about these methods on this article.

              【讨论】:

              • 如果要打印尾随零,则应删除 * 1 代码,例如6.40 MB.
              【解决方案10】:
              function bytesToHuman($bytes)
              {
                  $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
                  for ($i = 0; $bytes > 1024; $i++) $bytes /= 1024;
                  return round($bytes, 2) . ' ' . $units[$i];
              }
              

              信用:https://laracasts.com/discuss/channels/laravel/human-readable-file-size-and-time?page=1#reply=115796

              【讨论】:

                【解决方案11】:

                这就是我的使用方式,干净简单。 也可以这样使用:

                public function getHumanReadableFilesize(int $bytes, int $dec = 2): string
                {
                    $size   = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
                    $factor = floor((strlen($bytes) - 1) / 3);
                
                    return sprintf("%.{$dec}f %s", ($bytes / (1024 ** $factor)), $size[$factor]);
                }
                

                感谢@Márton Tamás 提出添加点赞评论的建议。

                【讨论】:

                  【解决方案12】:

                  这是我用于显示人类可读文件大小的自定义函数:

                  function getHumanReadableSize($bytes) {
                    if ($bytes > 0) {
                      $base = floor(log($bytes) / log(1024));
                      $units = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"); //units of measurement
                      return number_format(($bytes / pow(1024, floor($base))), 3) . " $units[$base]";
                    } else return "0 bytes";
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2010-11-08
                    • 2017-08-09
                    • 2014-10-16
                    • 2013-02-06
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多