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

如何使用Perl获得文件的大小(以兆字节为单位)?,perl,file-io,filesize,magic-numbers,Perl,File Io,Filesize,Magic Numbers,我想获取磁盘上文件的大小(以兆字节为单位)。使用-s操作符可以得到以字节为单位的大小,但我假设将其除以一个幻数是个坏主意: my $size_in_mb = (-s $fh) / (1024 * 1024); 我应该只使用一个只读变量来定义1024,还是有一种编程方式来获取一个KB中的字节数 编辑:更新了错误的计算。嗯,兆欧表中没有1024个字节,兆欧表中有1024个字节,兆欧表中有1024个字节 这就是说,1024是一个安全的“神奇”数字,在任何你希望你的程序工作的系统中都不会改变。1)你不

我想获取磁盘上文件的大小(以兆字节为单位)。使用
-s
操作符可以得到以字节为单位的大小,但我假设将其除以一个幻数是个坏主意:

my $size_in_mb = (-s $fh) / (1024 * 1024);
我应该只使用一个只读变量来定义1024,还是有一种编程方式来获取一个KB中的字节数


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

嗯,兆欧表中没有1024个字节,兆欧表中有1024个字节,兆欧表中有1024个字节

这就是说,1024是一个安全的“神奇”数字,在任何你希望你的程序工作的系统中都不会改变。

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


2) 为什么除以一个幻数是个坏主意?兆字节中的字节数不会改变。不要想得太多。

不要误解我的意思,但是:我认为将1024声明为神奇变量有点过分,这有点像“$1=1;$2=2;”等等

20多年来,一个千字节被错误地声明为1024字节,我严重怀疑操作系统制造商是否会纠正这个错误并将其改为1000字节


不过,有意义的是声明不明显的内容,比如“$MB=1024*1024”,因为它比1048576更可读。

因为-s运算符返回文件大小(以字节为单位),所以您可能应该执行以下操作

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

如果你需要一个圆的数字,可以使用int()。KB或MB的尺寸在不久的将来不会随时改变:)

我会把它读入一个变量,而不是使用一个幻数。即使神奇的数字不会改变,比如兆字节中的字节数,使用一个命名良好的常量也是一个很好的做法,因为它使代码更具可读性。它让其他人立刻明白了你的意图。

如果你想避免使用幻数,请尝试CPAN模块


当然,您可以创建一个函数来计算它。这是一个比在此实例中创建常量更好的解决方案

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

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

这是一个老问题,已经得到了正确的回答,但万一您的程序被限制在核心模块上,您不能在此处使用,您还有几个随时间推移收集的其他选项。我之所以保留它们,也是因为每一个都使用不同的Perl方法,这是一个很好的例子:

  • 示例1:使用状态避免每次重新初始化变量(在Perl5.16之前,您需要使用FeatureState或perl-E)

  • 示例4:使用
    +$n和。。。直到..
    获取数组的索引

#http://www.perlmonks.org/?node_id=378542
#! perl-slw
严格使用;
子标度{
我的($size,$n)=(shift,0);
++$n和$size/=1024,直到$size<1024;
返回sprintf“%.2f%s”,
$size,(qw[bytes-KB-GB])[$n];
}
我的$size=-s$ARGV[0];
打印“$ARGV[0]:”,缩放$size;

即使不能使用Number::Bytes::Human,也可以查看源代码以了解所有需要注意的事项

类似的情况是在米和公里之间转换。。。如果把1000这个“神奇”因素包括在内,你会觉得不好吗?这是一个永远不会改变的直接单位转换。。他们有不同的观点(错误的IMHO,但是嘿,他们有更多的钱)更新了这个问题。时间还早,请原谅我把千字节误认为兆字节。:)只需使用Number::Bytes::Human模块即可。比自己做容易得多,可读性也更高。在这一点上,我认为使用正确的千兆字节和千兆字节定义()应该是至关重要的。作为两个独立的实体,我们不应该担心这一点。如果需要的话,你可以很容易地从giga转换到gibi。刚刚发现它还可以将人类可读的字符串解析回字节!
sub size_in_mb {
    my $size_in_bytes = shift;
    return $size_in_bytes / (1024 * 1024);
}
    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
# 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;