How to show nice file sizes

I would like to be able to convert say 589432 to 583Kb. Thus making the
byte amounts of images easier to show users.

Ive used humanize for my strings, and while searching in the framework
docs (under core extensions) for a function to do the above i came
across the ago function for dates, but cant find one for computer
amounts.

On 9/28/06, Adam M. [email protected] wrote:

I would like to be able to convert say 589432 to 583Kb. Thus making the
byte amounts of images easier to show users.

Ive used humanize for my strings, and while searching in the framework
docs (under core extensions) for a function to do the above i came
across the ago function for dates, but cant find one for computer
amounts.

The rails extensions for bytes are found here
http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Numeric/Bytes.html

but they’re not really conversions. I think you would need to do some
work
to have it work nicely.

On Thursday 28 September 2006 07:55, Daniel N wrote:

[ “B”, “KB”, “MB”, “GB” etc] with the abbreviation set at an index such
that 1024 ** index will provide the correct unit. ie.
index = 0 => Byte
index = 1 => KB
etc

def format_nice_bytes( a_number )
index = ( Math.log( a_number ) / Math.log( 2 ) ).to_i / 10
“#{a_number.to_i / ( 1024 ** index ) } #{BYTE_UNITS[index]}”
end

would work, but you would be feeding processor cycles to the hogs
needlessly.

I am completely new to Ruby (Pythonista of many years), but I think
something
like this would work and be some orders of magnitude faster (and easier
to
read):

def format_nice_bytes(n)
[[1073741824, “GB”], [1048576, “MB”], [1024, “KB”], [0,
“B”]].each {|
u| if (n > u[0]) then return printf("%.2f %s",n/u[0], u[1]); end }
end

I am sure somebody more familiar with Ruby will come up with a far more
elegant and efficient solution
Horst

On 9/28/06, Daniel N [email protected] wrote:

docs (under core extensions) for a function to do the above i came

I thought this looked pretty interesting so I’ll give it a stab. There
is
no doubt much nicer ways to do this though. Like including it in the
Numeric module or something.

Anyway… here goes.

I’m assuming that there is an array with abberviated units available as
a
constant BYTE_UNITS
[ “B”, “KB”, “MB”, “GB” etc] with the abbreviation set at an index such
that
1024 ** index will provide the correct unit. ie.
index = 0 => Byte
index = 1 => KB
etc

def format_nice_bytes( a_number )
index = ( Math.log( a_number ) / Math.log( 2 ) ).to_i / 10
“#{a_number.to_i / ( 1024 ** index ) } #{BYTE_UNITS[index]}”
end

Hope that works for you. (and that you can beutify it!!)

Man i did not expect that response. Just goes to show how great the
rails community is.

I was asking if there was a command to perform that operation. I was
sure i had seen it before. Then while looking for something else in my
agile web book i came across it !!!

See page 347 in AWD v1.

human_size(123_456)

120.6 KB

other usefull operations

time_ago_in_words(date time value here)

116 days

On 9/28/06, Horst H. [email protected] wrote:

index = ( Math.log( a_number ) / Math.log( 2 ) ).to_i / 10

def format_nice_bytes(n)
[[1073741824, “GB”], [1048576, “MB”], [1024, “KB”], [0, “B”]].each
{|
u| if (n > u[0]) then return printf(“%.2f %s”,n/u[0], u[1]); end }
end

I am sure somebody more familiar with Ruby will come up with a far more
elegant and efficient solution
Horst
–~—

I do sometimes get carried away with open ended solutions…

Running a benchmark on the code (original method is 1, your suggestion
is 2,
and a modified version of your suggestion is 3) gives

format_nice_bytes1 0.031000 0.000000 0.031000 ( 0.032000)
format_nice_bytes2 0.110000 0.031000 0.141000 ( 0.234000)
format_nice_bytes3 0.062000 0.000000 0.062000 ( 0.063000)

But this doesn’t really mean much. There are two main differences that
are
super apparent to me with this one.

  1. each run through methods 2 and 3 had to create the array of units for
    every method call (very expensive)
  2. method 2 forced output to std out instead of just returning a string.

A refinement of taking the unit array out of the method into a constant
so
that it’s apples with apples on method 1 provides

format_nice_bytes1 0.031000 0.000000 0.031000 ( 0.031000)
format_nice_bytes2 0.110000 0.000000 0.110000 ( 0.234000)
format_nice_bytes3 0.047000 0.000000 0.047000 ( 0.047000)
format_nice_bytes4 0.031000 0.000000 0.031000 ( 0.031000)

There doesn’t look like there’s much in it between method 1 and 4, but 4
is
easier to read. I haven’t done many benchmarks though so I’d be more
than
happy to have other feedback.

I’ve attached the test file that I used and listed the methods below.

BYTE_UNITS = [“B”, “KB”, “MB”, “GB” ]
BYTE_UNITS2 =[[1073741824, “GB”], [1048576, “MB”], [1024, “KB”], [0,
“B”]]

def format_nice_bytes1( a_number )
index = ( Math.log( a_number ) / Math.log( 2 ) ).to_i / 10
“#{a_number.to_i / ( 1024 ** index ) } #{BYTE_UNITS[index]}”

end

def format_nice_bytes2(n)
[[1073741824, “GB”], [1048576, “MB”], [1024, “KB”], [0,
“B”]].each
{|u| if (n > u[0]) then return printf(“%.2f %s”,n/u[0], u[1]); end }
end

def format_nice_bytes3(n)
unit = [[1073741824, “GB”], [1048576, “MB”], [1024, “KB”], [0,
“B”]].detect{ |u| n > u[0] }
“#{n/unit[0]} #{unit[1]}”

end

def format_nice_bytes4(n)
unit = BYTE_UNITS2.detect{ |u| n > u[0] }
“#{n/unit[0]} #{unit[1]}”
end

On 9/29/06, Adam M. [email protected] wrote:

human_size(123_456)

120.6 KB

I thought there might be one… It sure was fun though… :wink: