Как мне получить размер файла в мегабайтах с помощью Perl?

StackOverflow https://stackoverflow.com/questions/511785

Вопрос

Я хочу получить размер файла на диске в мегабайтах.Используя -s оператор дает мне размер в байтах, но я предполагаю, что делить это на магическое число — плохая идея:

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

Должен ли я просто использовать переменную, доступную только для чтения, для определения 1024 или есть программный способ получить количество байтов в килобайте?

РЕДАКТИРОВАТЬ: Обновлен неверный расчет.

Это было полезно?

Решение

Если вы хотите избежать магических чисел, попробуйте модуль CPAN. Число::Байты::Человек.

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 — это безопасное «магическое» число, которое никогда не изменится ни в одной системе, в которой, как вы ожидаете, будет работать ваша программа.

Я бы прочитал это в переменную, а не использовал магическое число.Даже если магические числа не изменятся, например, количество байтов в мегабайте, использование хорошо названной константы является хорошей практикой, поскольку она делает ваш код более читабельным.Это сразу же дает понять всем остальным, каковы ваши намерения.

Это старый вопрос, и на него уже был дан правильный ответ, но на всякий случай ваша программа ограничена основными модулями и вы не можете использовать Число::Байты::Человек вот вам еще несколько вариантов, которые я собрал с течением времени.Я сохранил их еще и потому, что каждый из них использует свой подход Perl и является хорошим примером для ТИМТОВТДИ:

  • пример 1:использует состояние, чтобы избежать повторной инициализации переменной каждый раз (до версии Perl 5.16 вам нужно было использовать состояние функции или Perl -E)

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]);
    }
  • пример 2:используя карту сортировки

.

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]
  }
  • пример 3:Воспользуйтесь тем, что 1 Гб = 1024 Мб, 1 Мб = 1024 Кб и 1024 = 2**10:

.

# 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
  • пример 4:использование ++$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) Почему деление на магическое число — плохая идея?Не похоже, что количество байтов в мегабайте когда-либо изменится.Не обдумывайте слишком много вещей.

Не поймите меня неправильно, но:Я думаю, что объявление 1024 как магической переменной заходит слишком далеко, это немного похоже на «$ONE = 1;$TWO = 2;» и т. д.

Килобайт ошибочно объявлялся равным 1024 байтам уже более 20 лет, и я серьезно сомневаюсь, что производители операционных систем когда-либо исправят эту ошибку и изменят ее на 1000.

Однако что может иметь смысл, так это объявить неочевидные вещи, например «$megabyte = 1024 * 1024», поскольку это более читабельно, чем 1048576.

Поскольку оператор -s возвращает размер файла в байтах, вам, вероятно, следует сделать что-то вроде

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

и используйте int(), если вам нужна круглая цифра.Не похоже, что размеры КБ или МБ изменятся в ближайшем будущем :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top