我试图作出这样的转变,表示字节以“美化了一番”格式的字符串整数的方法。
这是我的一半工作的尝试:
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
我究竟做错了什么?
Answer 1:
如何对文件大小的宝石? 这似乎是能够从字节(等格式)转换成漂亮的打印值转换:
例:
Filesize.from("12502343 B").pretty # => "11.92 MiB"
http://rubygems.org/gems/filesize
Answer 2:
什么标准的Rails数帮手 - 如果你使用Rails使用它?
http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_to_human_size
number_to_human_size(number, options = {})
?
Answer 3:
我与@大卫同意,这可能是最好使用现有的解决方案,但要回答你的问题对你做错了什么:
- 主要错误是将
s
的self
,而不是周围的其他方式。 - 你真的想通过以前的划分
s
,所以划分s
1024。 - 这样做整数运算会给你混乱的结果,所以转换为浮动。
- 也许圆了答案。
所以:
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
让你:
1.to_filesize
# => "1.0B"
1020.to_filesize
# => "1020.0B"
1024.to_filesize
# => "1.0KB"
1048576.to_filesize
# => "1.0MB"
同样,我不建议实际上这样做,但它似乎值得纠正的错误。
Answer 4:
这是我的解决方案:
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
相比其他解决方案,它更简单,更高效,并产生更正确的输出。
格式
无论to_filesize
和to_human
有大数字的问题。 format_mb
拥有其中,例如“1 MIB”被认为是“1024昆明植物研究所”,这是值得一些人可能想,但肯定不是我一个奇怪的情况。
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
性能
此外,它具有最佳的性能。
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)
我测试了一个现实的随机数生成每个实现:
def numbers
Enumerator.new do |enum|
1000000.times do
exp = rand(5)
num = rand(1024 ** exp)
enum.yield num
end
end
end
Answer 5:
你得到点添加一个方法整数,但这似乎更具体的文件,所以我建议用文件弄乱左右,加入到文件名为.prettysize()的方法说。
但在这里是使用迭代的替代解决方案,并且避免了印刷的单字节浮子:-)
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
Answer 6:
@Darshan计算的解决方案仅仅是局部的在这里。 由于哈希键,但不保证有序的这种做法将无法可靠地工作。 你可以做这样的事情to_filesize方法中解决这个问题,
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 }
}
这是我最后做了内浮动类似的方法,
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
文章来源: Pretty file size in Ruby?