如何使用Perl获取文件大小(以兆字节为单位)?

时间:2009-02-04 15:18:15

标签: perl file-io filesize magic-numbers

我希望以兆字节为单位获取磁盘上文件的大小。使用-s运算符给出了字节大小,但我假设将其除以幻数是个坏主意:

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

我应该只使用只读变量来定义1024,还是以编程方式获取千字节的字节数?

编辑:更新了错误的计算。

8 个答案:

答案 0 :(得分:30)

如果您想避免幻数,请尝试使用CPAN模块Number::Bytes::Human

use Number::Bytes::Human qw(format_bytes);
my $size = format_bytes(-s $file); # 4.5M

答案 1 :(得分:6)

你当然可以创建一个计算它的函数。这是比在这种情况下创建常量更好的解决方案。

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

不需要常数。将1024更改为某种变量/常量不会使此代码更具可读性。

答案 2 :(得分:4)

嗯,一个meg中没有1024个字节,K中有1024个字节,而一个meg中有1024个K ...

也就是说,1024是一个安全的“魔术”数字,在你可以期待你的程序工作的任何系统中永远不会改变。

答案 3 :(得分:4)

我会把它读成变量,而不是使用幻数。即使魔术数字不会改变,就像兆字节中的字节数一样,使用一个名为constant的常量也是一种很好的做法,因为它使你的代码更具可读性。这使得其他人立即明白你的意图。

答案 4 :(得分:4)

这是一个老问题,并且已经得到了正确的解答,但是为了防止你的程序被限制在核心模块而你不能在这里使用Number::Bytes::Human,你还有其他一些我随时间收集的选项。我也保留了它们,因为每个人都使用不同的Perl方法,并且是TIMTOWTDI的一个很好的例子:

  • 示例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,也请查看源代码以查看您需要注意的所有事项。

答案 5 :(得分:1)

1)你不需要1024.这给你千字节。你想要1024 * 1024或1048576。

2)为什么除以幻数是个坏主意?它不像兆字节中的字节数会改变。不要过分思考。

答案 6 :(得分:1)

不要误解我的意思,但是:我认为将1024声称为魔术变量有点太过分了,这有点像“$ ONE = 1; $ TWO = 2;”等

自20多年以来,Kilobyte被错误地声称为1024字节,我严重怀疑操作系统制造商是否会纠正该错误并将其更改为1000.

可能有意义的是宣布非显而易见的东西,比如“$ megabyte = 1024 * 1024”,因为它比1048576更具可读性。

答案 7 :(得分:1)

由于-s运算符以字节为单位返回文件大小,因此您可能应该执行类似

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

如果需要圆形图,请使用int()。它不像KB或MB的维度在不久的将来会随时改变:)