Perl を使用してファイルのサイズをメガバイト単位で取得するにはどうすればよいですか?

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

質問

ディスク上のファイルのサイズをメガバイト単位で取得したいと考えています。の使用 -s 演算子はサイズをバイト単位で返しますが、これをマジックナンバーで割るのは悪い考えだと仮定します。

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

読み取り専用変数を使用して 1024 を定義する必要がありますか、それとも 1 キロバイト単位のバイト数を取得するプログラム的な方法はありますか?

編集: 間違った計算を更新しました。

役に立ちましたか?

解決

マジックナンバーを避けたい場合は、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 ある種の変数/定数を追加しても、このコードは読みやすくなりません。

そうですね、1 メガには 1024 バイトはありません。K には 1024 バイトがあり、1 メガには 1024 K があります...

とはいえ、1024 は安全な「魔法の」数字であり、プログラムが動作すると予想されるどのシステムでも決して変更されることはありません。

マジックナンバーを使用するのではなく、これを変数に読み込みます。メガバイトのバイト数のようにマジック ナンバーが変更されない場合でも、コードが読みやすくなるため、適切な名前の定数を使用することをお勧めします。そうすることで、あなたの意図が他の人にすぐに分かります。

これは古い質問であり、すでに正しく回答されていますが、プログラムがコアモジュールに制限されており、使用できない場合に備えて、 数値::バイト::人間 ここでは、私が時間をかけて収集した他のいくつかのオプションを紹介します。それぞれが異なる Perl アプローチを使用しており、 ティムトウディ:

  • 例1:変数を毎回再初期化するのを避けるために state を使用します (perl 5.16 より前では、feature state または 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 Gb = 1024 Mb、1 Mb = 1024 Kb、および 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;" など

1 キロバイトは 20 年以上にわたって 1024 バイトと誤って宣言されてきましたが、オペレーティング システムの製造元がそのバグを修正して 1000 バイトに変更するかどうかは非常に疑わしいです。

ただし、「$megabyte = 1024 * 1024」のような自明ではないものを宣言することは、1048576 よりも読みやすいため、意味があると考えられます。

-s 演算子はファイル サイズをバイト単位で返すため、おそらく次のようなことを行う必要があります。

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

丸い数字が必要な場合は int() を使用します。KB や MB のサイズが近い将来いつでも変わるわけではありません:)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top