14

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

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

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

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

4

8 回答 8

33

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

use Number::Bytes::Human qw(format_bytes);
my $size = format_bytes(-s $file); # 4.5M
于 2009-02-04T18:25:22.563 回答
9

这是一个老问题,已经得到了正确的回答,但以防万一您的程序受限于核心模块并且您不能在这里使用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:使用 of++$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,也请查看源代码以了解您需要注意的所有事项。

于 2014-03-16T09:43:33.660 回答
7

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

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

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

于 2009-02-05T16:18:18.790 回答
4

嗯,一个兆不是 1024 个字节,一个 K 有 1024 个字节,一个兆是 1024 K...

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

于 2009-02-04T15:19:44.043 回答
4

我会将其读入变量而不是使用幻数。即使幻数不会改变,比如 1 MB 中的字节数,使用命名良好的常量也是一种很好的做法,因为它使您的代码更具可读性。它让其他人立即明白你的意图是什么。

于 2009-02-04T15:34:03.687 回答
1

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

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

于 2009-02-04T15:20:51.047 回答
1

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

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

不过,可能有意义的是声明不明显的东西,比如“$megabyte = 1024 * 1024”,因为它比 1048576 更具可读性。

于 2009-02-04T15:21:57.253 回答
1

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

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

如果您需要一个圆形,请使用 int() 。这不像 KB 或 MB 的尺寸会在不久的将来随时改变 :)

于 2009-02-04T15:26:07.260 回答