Ответ 1
Если вы хотите избежать магических чисел, попробуйте модуль CPAN Number::Bytes::Human.
use Number::Bytes::Human qw(format_bytes);
my $size = format_bytes(-s $file); # 4.5M
Я хочу получить размер файла на диске в мегабайтах. Использование оператора -s
дает мне размер в байтах, но я собираюсь предположить, что деление этого на магическое число - плохая идея:
my $size_in_mb = (-s $fh) / (1024 * 1024);
Должен ли я использовать переменную только для чтения для определения 1024 или есть программный способ получить количество байтов в килобайте?
EDIT: Обновлен неверный расчет.
Если вы хотите избежать магических чисел, попробуйте модуль CPAN Number::Bytes::Human.
use Number::Bytes::Human qw(format_bytes);
my $size = format_bytes(-s $file); # 4.5M
Вы могли бы, конечно, создать функцию для вычисления этого. Это лучшее решение, чем создание констант в этом случае.
sub size_in_mb {
my $size_in_bytes = shift;
return $size_in_bytes / (1024 * 1024);
}
Нет необходимости в константах. Изменение 1024
на какую-либо переменную/константу не сделает этот код более удобочитаемым.
Ну, там не 1024 байта в мега, там 1024 байта в К и 1024 К в мега...
Таким образом, 1024 - это безопасный "волшебный" номер, который никогда не изменится в любой системе, в которой вы можете ожидать, что ваша программа будет работать.
Я бы прочитал это в переменной, а не использовал магическое число. Даже если магические числа не будут меняться, как и количество байтов в мегабайте, использование хорошо названной константы является хорошей практикой, потому что это делает ваш код более удобочитаемым. Это сразу становится очевидным для всех, каковы ваши намерения.
Это старый вопрос и уже правильно ответил, но на всякий случай ваша программа ограничена основными модулями, и вы не можете использовать Number:: Bytes:: Human здесь у вас есть несколько других вариантов, которые я собирал с течением времени. Я сохранил их также потому, что каждый из них использует другой подход Perl и является хорошим примером для TIMTOWTDI:
http://kba49.wordpress.com/2013/02/17/format-file-sizes-human-readable-in-perl/
sub formatSize {
my $size = shift;
my $exp = 0;
state $units = [qw(B KB MB GB TB PB)];
for (@$units) {
last if $size < 1024;
$size /= 1024;
$exp++;
}
return wantarray ? ($size, $units->[$exp]) : sprintf("%.2f %s", $size, $units->[$exp]);
}
.
sub scaledbytes {
# http://www.perlmonks.org/?node_id=378580
(sort { length $a <=> length $b
} map { sprintf '%.3g%s', $_[0]/1024**$_->[1], $_->[0]
}[" bytes"=>0]
,[KB=>1]
,[MB=>2]
,[GB=>3]
,[TB=>4]
,[PB=>5]
,[EB=>6]
)[0]
}
.
# http://www.perlmonks.org/?node_id=378544
my $kb = 1024 * 1024; # set to 1 Gb
my $mb = $kb >> 10;
my $gb = $mb >> 10;
print "$kb kb = $mb mb = $gb gb\n";
__END__
1048576 kb = 1024 mb = 1 gb
++$n and ... until ..
для получения индекса для массива.
# http://www.perlmonks.org/?node_id=378542
#! perl -slw
use strict;
sub scaleIt {
my( $size, $n ) =( shift, 0 );
++$n and $size /= 1024 until $size < 1024;
return sprintf "%.2f %s",
$size, ( qw[ bytes KB MB GB ] )[ $n ];
}
my $size = -s $ARGV[ 0 ];
print "$ARGV[ 0 ]: ", scaleIt $size;
Даже если вы не можете использовать Number:: Bytes:: Human, посмотрите исходный код, чтобы увидеть все, что вам нужно знать.
1) Вы не хотите 1024. Это дает вам килобайты. Вы хотите 1024 * 1024 или 1048576.
2) Почему деление на магическое число будет плохой идеей? Это не похоже на то, что количество байтов в мегабайте будет когда-либо изменяться. Не слишком сильно задумывайтесь над вещами.
Так как оператор -s возвращает размер файла в байтах, вы, вероятно, должны делать что-то вроде
my $size_in_mb = (-s $fh) / (1024 * 1024);
и используйте int(), если вам нужна круглая фигура. Это не похоже, что размеры KB или MB будут меняться в любое время в ближайшем будущем:)
Не поймите меня неправильно, но: я думаю, что объявление 1024 как Magic Variable немного слишком далеко, что немного похоже на "$ ONE = 1; $TWO = 2;" и др.
A Kilobyte ошибочно объявлен как 1024 байта с более чем 20 лет, и я серьезно сомневаюсь, что производители операционной системы когда-либо исправят эту ошибку и изменят ее до 1000.
Что может иметь смысл, так это объявить неочевидные вещи, например "$ megabyte = 1024 * 1024", так как это более читаемо, чем 1048576.