Pretty file size in Ruby?

后端 未结 7 1855
半阙折子戏
半阙折子戏 2020-12-13 20:06

I\'m trying to make a method that converts an integer that represents bytes to a string with a \'prettied up\' format.

Here\'s my half-working attempt:



        
相关标签:
7条回答
  • 2020-12-13 20:32

    This is my solution:

    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 += 1 if (size.to_f / 1024 ** exp >= 1024 - 0.05)
      exp = 6 if exp > 6 
    
      '%.1f %s' % [size.to_f / 1024 ** exp, units[exp]]
    end
    

    Compared to other solutions it's simpler, more efficient, and generates a more proper output.

    Format

    Both to_filesize and to_human have issues with big numbers. format_mb has a weird case where for example '1 MiB' is considered '1024 KiB' which is something some people might want, but certainly not me.

        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
    

    Performance

    Also, it has the best performance.

                          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)
    

    I tested each implementation with a realistic random number generator:

    def numbers
      Enumerator.new do |enum|
        1000000.times do
          exp = rand(5)
          num = rand(1024 ** exp)
          enum.yield num
        end
      end
    end
    
    0 讨论(0)
提交回复
热议问题