繁体   English   中英

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

[英]How do I get the size of a file in megabytes using Perl?

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

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

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

编辑:更新了不正确的计算。

如果您想避免使用幻数,请尝试使用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更改为某种变量/常量将不会使此代码更具可读性。

这是一个古老的问题,并且已经得到了正确的答案,但是以防万一您的程序被限制在核心模块上,并且您无法使用Number :: Bytes :: Human ,随着时间的推移,您还有其他几种选择。 我之所以保留它们,是因为每个人都使用不同的Perl方法,并且是TIMTOWTDI的一个很好的例子:

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

http://kba49.wordpress.com/2013/02/17/format-file-sizes-human-read-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,也请查看源代码以查看您需要了解的所有内容。

嗯,兆字节中没有1024字节,兆字节中没有1024字节,兆字节中没有1024 K ...

也就是说,1024是一个安全的“魔术”数字,在可以预期您的程序可以运行的任何系统中,它都不会改变。

我会将其读入变量而不是使用幻数。 即使幻数不会改变(例如兆字节中的字节数),使用良好命名的常量也是一个好习惯,因为它会使您的代码更具可读性。 它使其他人立即知道您的意图是什么。

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

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

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

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

不过可能有意义的是声明非显而易见的内容,例如“ $ megabyte = 1024 * 1024”,因为它比1048576更具可读性。

由于-s运算符返回文件大小(以字节为单位),因此您可能应该这样做

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

如果需要圆形图形,请使用int()。 这并不意味着KB或MB的大小在不久的将来会随时发生变化:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM