Ruby中的漂亮文件大小?

Tea*_*ast 21 ruby byte integer filesize

我正在尝试创建一个方法,将表示字节的整数转换为带有'prettied up'格式的字符串.

这是我的半工作尝试:

class Integer
  def to_filesize
    {
      'B'  => 1024,
      'KB' => 1024 * 1024,
      'MB' => 1024 * 1024 * 1024,
      'GB' => 1024 * 1024 * 1024 * 1024,
      'TB' => 1024 * 1024 * 1024 * 1024 * 1024
    }.each_pair { |e, s| return "#{s / self}#{e}" if self < s }
  end
end
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Wil*_* E. 28

如果你在Rails中使用它 - 那么标准的Rails编号助手呢?

http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_human_size

number_to_human_size(number, options = {})


Dav*_*d P 27

Filesize宝石怎么样?它似乎能够从字节(和其他格式)转换为漂亮的打印值:

例:

Filesize.from("12502343 B").pretty      # => "11.92 MiB"
Run Code Online (Sandbox Code Playgroud)

http://rubygems.org/gems/filesize

  • 该 gem 未维护并存档:https://github.com/dominikh/filesize (2认同)

Dar*_*tle 14

我同意@David认为最好使用现有的解决方案,但回答你关于你做错的问题:

  1. 主要错误是将s通过self,而不是周围的其他方式.
  2. 你真的想要除以前一个s,所以除以s1024.
  3. 进行整数运算会给你带来令人困惑的结果,所以转换为float.
  4. 也许围绕着答案.

所以:

class Integer
  def to_filesize
    {
      'B'  => 1024,
      'KB' => 1024 * 1024,
      'MB' => 1024 * 1024 * 1024,
      'GB' => 1024 * 1024 * 1024 * 1024,
      'TB' => 1024 * 1024 * 1024 * 1024 * 1024
    }.each_pair { |e, s| return "#{(self.to_f / (s / 1024)).round(2)}#{e}" if self < s }
  end
end
Run Code Online (Sandbox Code Playgroud)

让你:

1.to_filesize
# => "1.0B"
1020.to_filesize
# => "1020.0B" 
1024.to_filesize
# => "1.0KB" 
1048576.to_filesize
# => "1.0MB"

同样,我不建议实际这样做,但似乎值得纠正错误.


Fel*_*peC 7

这是我的解决方案:

def filesize(size)
  units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'Pib', 'EiB']

  return '0.0 B' if size == 0
  exp = (Math.log(size) / Math.log(1024)).to_i
  exp = 6 if exp > 6 

  '%.1f %s' % [size.to_f / 1024 ** exp, units[exp]]
end
Run Code Online (Sandbox Code Playgroud)

与其他解决方案相比,它更简单,更有效,并产生更合适的输出。

格式

双方to_filesizeto_human有大数字的问题。format_mb有一种奇怪的情况,例如“ 1 MiB”被认为是“ 1024 KiB”,这是某些人可能想要的东西,但我当然不是。

    origin:       filesize    to_filesize      format_mb       to_human
       0 B:          0.0 B           0.0B            0 b         0.00 B
       1 B:          1.0 B           1.0B            1 b         1.00 B
      10 B:         10.0 B          10.0B           10 b        10.00 B
    1000 B:       1000.0 B        1000.0B         1000 b      1000.00 B
     1 KiB:        1.0 KiB          1.0KB         1024 b        1.00 KB
   1.5 KiB:        1.5 KiB          1.5KB       1536.0 b        1.50 KB
    10 KiB:       10.0 KiB         10.0KB      10.000 kb       10.00 KB
   100 KiB:      100.0 KiB        100.0KB     100.000 kb      100.00 KB
  1000 KiB:     1000.0 KiB       1000.0KB    1000.000 kb     1000.00 KB
     1 MiB:        1.0 MiB          1.0MB    1024.000 kb        1.00 MB
     1 Gib:        1.0 GiB          1.0GB    1024.000 mb        1.00 GB
     1 TiB:        1.0 TiB          1.0TB    1024.000 gb        1.00 TB
     1 PiB:        1.0 Pib          ERROR    1024.000 tb        1.00 PB
     1 EiB:        1.0 EiB          ERROR    1024.000 pb        1.00 EB
     1 ZiB:     1024.0 EiB          ERROR    1024.000 eb          ERROR
     1 YiB:  1048576.0 EiB          ERROR 1048576.000 eb          ERROR
Run Code Online (Sandbox Code Playgroud)

性能

而且,它具有最佳性能。

                      user     system      total        real
filesize:         2.740000   0.000000   2.740000 (  2.747873)
to_filesize:      3.560000   0.000000   3.560000 (  3.557808)
format_mb:        2.950000   0.000000   2.950000 (  2.949930)
to_human:         5.770000   0.000000   5.770000 (  5.783925)
Run Code Online (Sandbox Code Playgroud)

我用一个现实的随机数生成器测试了每个实现:

def numbers
  Enumerator.new do |enum|
    1000000.times do
      exp = rand(5)
      num = rand(1024 ** exp)
      enum.yield num
    end
  end
end
Run Code Online (Sandbox Code Playgroud)