Pretty file size in Ruby?

后端 未结 7 1854
半阙折子戏
半阙折子戏 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:11

    If you use it with Rails - what about standard Rails number helper?

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

    number_to_human_size(number, options = {})

    ?

    0 讨论(0)
  • 2020-12-13 20:14

    Here is a method using log10:

    def number_format(n)
       n2 = Math.log10(n).to_i / 3
       return '%.3f' % (n / 1e3 ** n2) + ['', ' k', ' M', ' G'][n2]
    end
    
    s = number_format(9012345678e0)
    puts s == '9.012 G'
    

    https://ruby-doc.org/core/Math.html#method-c-log10

    0 讨论(0)
  • 2020-12-13 20:25

    You get points for adding a method to Integer, but this seems more File specific, so I would suggest monkeying around with File, say by adding a method to File called .prettysize().

    But here is an alternative solution that uses iteration, and avoids printing single bytes as float :-)

    def format_mb(size)
      conv = [ 'b', 'kb', 'mb', 'gb', 'tb', 'pb', 'eb' ];
      scale = 1024;
    
      ndx=1
      if( size < 2*(scale**ndx)  ) then
        return "#{(size)} #{conv[ndx-1]}"
      end
      size=size.to_f
      [2,3,4,5,6,7].each do |ndx|
        if( size < 2*(scale**ndx)  ) then
          return "#{'%.3f' % (size/(scale**(ndx-1)))} #{conv[ndx-1]}"
        end
      end
      ndx=7
      return "#{'%.3f' % (size/(scale**(ndx-1)))} #{conv[ndx-1]}"
    end
    
    0 讨论(0)
  • 2020-12-13 20:25

    @Darshan Computing's solution is only partial here. Since the hash keys are not guaranteed to be ordered this approach will not work reliably. You could fix this by doing something like this inside the to_filesize method,

     conv={
          1024=>'B',
          1024*1024=>'KB',
          ...
     }
     conv.keys.sort.each { |s|
         next if self >= s
         e=conv[s]
         return "#{(self.to_f / (s / 1024)).round(2)}#{e}" if self < s }
     }
    

    This is what I ended up doing for a similar method inside Float,

     class Float
       def to_human
         conv={
           1024=>'B',
           1024*1024=>'KB',
           1024*1024*1024=>'MB',
           1024*1024*1024*1024=>'GB',
           1024*1024*1024*1024*1024=>'TB',
           1024*1024*1024*1024*1024*1024=>'PB',
           1024*1024*1024*1024*1024*1024*1024=>'EB'
         }
         conv.keys.sort.each { |mult|
            next if self >= mult
            suffix=conv[mult]
            return "%.2f %s" % [ self / (mult / 1024), suffix ]
         }
       end
     end
    
    0 讨论(0)
  • 2020-12-13 20:26

    How about the Filesize gem ? It seems to be able to convert from bytes (and other formats) into pretty printed values:

    example:

    Filesize.from("12502343 B").pretty      # => "11.92 MiB"
    

    http://rubygems.org/gems/filesize

    0 讨论(0)
  • 2020-12-13 20:27

    I agree with @David that it's probably best to use an existing solution, but to answer your question about what you're doing wrong:

    1. The primary error is dividing s by self rather than the other way around.
    2. You really want to divide by the previous s, so divide s by 1024.
    3. Doing integer arithmetic will give you confusing results, so convert to float.
    4. Perhaps round the answer.

    So:

    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
    

    lets you:

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

    Again, I don't recommend actually doing that, but it seems worth correcting the bugs.

    0 讨论(0)
提交回复
热议问题