views:

963

answers:

7

I want to get the size of a file on disk in megabytes. Using the -s operator gives me the size in bytes, but I'm going to assume that then diving this by a magic number is a bad idea:

my $size_in_mb = (-s $fh) / (1024 * 1024);

Should I just use a read-only variable to define 1024 or is there a programmatic way to obtain the size of a byte?

EDIT: Updated the incorrect calculation.

+4  A: 

Well, there's not 1024 bytes in a meg, there's 1024 bytes in a K, and 1024 K in a meg...

That said, 1024 is a safe "magic" number that will never change in any system you can expect your program to work in.

a similar situation would be converting between meters and kilometers... would you feel bad about including the "magic" factor of 1000? This is a straight unit conversion that will NEVER change.
rmeador
talk to marketing .. they have a different opinion (wrong IMHO, but hey, they have more money)
lexu
Updated the question. It's early so forgive my mistaking of kilobytes for megabytes. :)
cowgod
Even if the magic number is "safe", your code is more readable having a named constant instead. Consider physical constants like G, c, or mathematical ones like pi or e. Sure, they will never change in our universe, but your expressions are much more readable if used by name rather than by value.
Adam Bellaire
Just use the Number::Bytes::Human module for this. Much easier than doing it yourself, and much more readable.
jrockway
One place I worked (an IPS), a gigabyte was defined as 1024Mb for some purposes, but 1000Mb for other purposes. So if there are multiple ways to define a Gigabyte (or a Megabyte), then the magic numbers can change based on which definition is being used.
noswonky
At that point, I think it should be critical to use proper definitions of gigabyte and gibibyte (http://en.wikipedia.org/wiki/GiB). As two separate entities, we shouldn't worry about that. You can always easily convert from giga to gibi if need be.
+1  A: 

1) You don't want 1024. That gives you kilobytes. You want 1024*1024, or 1048576.

2) Why would dividing by a magic number be a bad idea? It's not like the number of bytes in a megabyte will ever change. Don't overthink things too much.

Chris Lutz
A: 

Don't get me wrong, but: I think that declaring 1024 as a Magic Variable goes a bit too far, that's a bit like "$ONE = 1; $TWO = 2;" etc.

A Kilobyte has been falsely declared as 1024 Bytes since more than 20 years, and I seriously doubt that the operating system manufacturers will ever correct that bug and change it to 1000.

What could make sense though is to declare non-obvious stuff, like "$megabyte = 1024 * 1024" since that is more readable than 1048576.

Michael Stum
A: 

Since the -s operator returns the file size in bytes you should probably be doing something like

my $size_in_mb = (-s $fh) / (1024 * 1024);

and use int() if you need a round figure. It's not like the dimensions of KB or MB is going to change anytime in the near future :)

muteW
+3  A: 

I would read this into a variable rather than use a magic number. Even if magic numbers are not going to change, like the number of bytes in a megabyte, using a well named constant is a good practice because it makes your code more readable. It makes it immediately apparent to everybody else what your intention is.

Doug R
+13  A: 

If you'd like to avoid magic numbers, try the CPAN module Number::Bytes::Human.

use Number::Bytes::Human qw(format_bytes);
my $size = format_bytes(-s $file); # 4.5M
jrockway
This module works great, thanks.
cowgod
+2  A: 

You could of course create a function for calculating this. That is a better solution than creating constants in this instance.

sub size_in_mb {
    my $size_in_bytes = shift;
    return $size_in_bytes / (1024 * 1024);
}

No need for constants. Changing the 1024 to some kind of variable/constant won't make this code more readable.

Peter Stuifzand