From: relaxmike on
Hi,

I searched for a Tcl snippet to convert a file size in bytes into
something more readable by a human, and I did not find it.
I looked in the excellent Tcllib package fileutil, I did not
find anything related to my problem.

So I did my own, which I copied on the wiki at :
http://wiki.tcl.tk/1676

The base block consists in computing the power of 1024.
The simplest is to use a "while" loop and divide the size
by 1024, until 1024 is reached.

proc hrfilesize::kilobytespower {size} {
set newsize $size
set power 0
while {$newsize >= $hrfilesize::kilobytes } {
incr power
set newsize [expr {$newsize / double($hrfilesize::kilobytes)}]
}
return $power
}

Then it is easy to use the power to compute the new size unit.
The method is based on the following map :

variable powertounitmap [list 0 "bytes" \
1 "Kbytes" \
2 "Mbytes" \
3 "Gbytes" \
4 "Tbytes"]

The last step is to use the power to compute the file size
in the new size unit and format the real to get a sexy real number.

proc hrfilesize::bytestohr {size {fmt "%.1f"}} {
set power [hrfilesize::kilobytespower $size]
# Limits the power to 4
if {$power>4} then {
set power 4
}
array set unitarray $hrfilesize::powertounitmap
set unit $unitarray($power)
set factor [expr {pow($hrfilesize::kilobytes,$power)}]
set reducedsize [expr {$size/$factor}]
set shortdouble [format $fmt $reducedsize]
set result "$shortdouble $unit"
return $result
}

I strongly suspect that I am not the first one to write
these lines, isn'it ?
If yes, I will remove my lines from the wiki and puts the correct
link instead.

Regards,

Michaƫl
From: billposer on
I'm not sure that this makes the transition from one unit to another
at the right point. If I apply it to 1,031,000 the result is "1006.8
Kbytes", where I would expect it to be "1.0 Mbytes" (or "0.98 Mbytes"
if we increase the precision). But maybe not. The problem is that even
though K, M, etc. are defined in terms of 1024 byte multipliers, our
expectation, I think, is that the value should not exceed 1000.0.

A second comment is that it is increasingly common to reserve K, M,
etc. for the true SI units, that is, with K=10^3, M=10^6, etc., and
use Ki for 1024, Mi for 1024^2, etc. You might provide the for both
types of unit.
From: Bryan Oakley on
billposer(a)alum.mit.edu wrote:
> I'm not sure that this makes the transition from one unit to another
> at the right point. If I apply it to 1,031,000 the result is "1006.8
> Kbytes", where I would expect it to be "1.0 Mbytes" (or "0.98 Mbytes"
> if we increase the precision). But maybe not. The problem is that even
> though K, M, etc. are defined in terms of 1024 byte multipliers, our
> expectation, I think, is that the value should not exceed 1000.0.
>
> A second comment is that it is increasingly common to reserve K, M,
> etc. for the true SI units, that is, with K=10^3, M=10^6, etc., and
> use Ki for 1024, Mi for 1024^2, etc. You might provide the for both
> types of unit.

I agree with the assessment that humans think in terms of 1K=1000 rather
than 1024. If the point is to make something human readable, 1 megabyte
is much more friendly than 1006.8 Kbytes. When I've written routines
like this I always make the cutoff 1000.

As for K/Ki, M/Mi, I hate the distinction. I understand the reasoning
but I suspect most people don't, and for the vast majority of cases, who
cares? Is it really important to know about those few extra bits? I say,
unless you are using it for advertising (ie: making promises about
capacity), stick with what is simple and common.
From: billposer on
On Jun 20, 4:02 pm, Bryan Oakley <oak...(a)bardo.clearlight.com> wrote:
> As for K/Ki, M/Mi, I hate the distinction. I understand the reasoning
> but I suspect most people don't, and for the vast majority of cases, who
> cares? Is it really important to know about those few extra bits? I say,
> unless you are using it for advertising (ie: making promises about
> capacity), stick with what is simple and common.

For many applications, I agree. But note that the difference becomes
potentially significant as sizes increase. At the gigabyte level, the
difference is 7%, at the terabyte level, 10%. If, for example, you
want to know whether some data will fit into available storage, that
could matter.
From: slebetman on
On Jun 21, 1:16 am, relaxmike <michael.bau...(a)gmail.com> wrote:
> Hi,
>
> I searched for a Tcl snippet to convert a file size in bytes into
> something more readable by a human, and I did not find it.
> I looked in the excellent Tcllib package fileutil, I did not
> find anything related to my problem.
>
> So I did my own, which I copied on the wiki at :http://wiki.tcl.tk/1676
>
> The base block consists in computing the power of 1024.
> The simplest is to use a "while" loop and divide the size
> by 1024, until 1024 is reached.
>
> proc hrfilesize::kilobytespower {size} {
> set newsize $size
> set power 0
> while {$newsize >= $hrfilesize::kilobytes } {
> incr power
> set newsize [expr {$newsize / double($hrfilesize::kilobytes)}]
> }
> return $power
>
> }
>
> Then it is easy to use the power to compute the new size unit.
> The method is based on the following map :
>
> variable powertounitmap [list 0 "bytes" \
> 1 "Kbytes" \
> 2 "Mbytes" \
> 3 "Gbytes" \
> 4 "Tbytes"]
>
> The last step is to use the power to compute the file size
> in the new size unit and format the real to get a sexy real number.
>
> proc hrfilesize::bytestohr {size {fmt "%.1f"}} {
> set power [hrfilesize::kilobytespower $size]
> # Limits the power to 4
> if {$power>4} then {
> set power 4
> }
> array set unitarray $hrfilesize::powertounitmap
> set unit $unitarray($power)
> set factor [expr {pow($hrfilesize::kilobytes,$power)}]
> set reducedsize [expr {$size/$factor}]
> set shortdouble [format $fmt $reducedsize]
> set result "$shortdouble $unit"
> return $result
>
> }
>
> I strongly suspect that I am not the first one to write
> these lines, isn'it ?
> If yes, I will remove my lines from the wiki and puts the correct
> link instead.
>

See http://wiki.tcl.tk/10874

For the content it holds, that page has the most unfortunate of names
(I only remember it because I wrote some code in it).
The original code is by RS, and as is usual with his code it is clear,
concise and highly readable (personally I'd say beautiful).
Scroll down for versions supporting both metric and binary.