【问题标题】:Is there a more efficient way to generate a random file in Perl?有没有更有效的方法在 Perl 中生成随机文件?
【发布时间】:2010-08-10 00:42:42
【问题描述】:

这是我的第一个 Perl 脚本。曾经:

#!/usr/bin/perl

if ($#ARGV < 1) { die("usage: <size_in_bytes> <file_name>\n"); }

open(FILE,">" . $ARGV[0]) or die "Can't open file for writing\n";

# you can control the range of characters here
my $minimum = 32;
my $range = 96;

for ($i=0; $i< $ARGV[1]; $i++) {
    print FILE chr(int(rand($range)) + $minimum);
}

close(FILE);

它的目的是generate a file in a specified size filled with random characters

它可以工作,但速度很慢。写入一个 10MB 的随机文件需要几秒钟。
有没有人有关于如何使它更快/更好的建议/提示?也请随时指出常见的新手错误。

【问题讨论】:

    标签: perl file-io random


    【解决方案1】:
    1. 您可以要求rand 在您每次调用它时为您创造多个价值。
    2. 在调用print 之前收集几个字符。一次打印一个字符效率很低。

     

    for (my $bytes = 0; $bytes < $num_bytes; $bytes += 4) {
        my $rand = int(rand($range ** 4));
        my $string = '';
        for (1..4) {
            $string .= chr($rand % $range + $minimum);
            $rand = int($rand / $range);
        }
        print FILE $string;
    }
    

    【讨论】:

    • 认为 perl 在发送到流的 4k 块中效果最好。与更改流缓冲区大小相关的 SO:stackoverflow.com/questions/1251062/…
    • 你为什么使用my $rand = int(rand($range ** 4))chr($rand % $range + $minimum)而不是my $rand = int(rand($range)chr($rand + $minimum)
    • rand($range**4) 包含足够的信息来生成 4 个随机字符
    • 但是rand($range) 不是也符合这个标准吗?
    【解决方案2】:

    如果您需要某个范围内的随机数,我不知道更有效的方法。您的脚本已根据我的喜好进行了调整:

    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    die("usage: $0 <size_in_bytes> <file_name>\n") unless @ARGV == 2;
    
    my ($num_bytes, $fname) = @ARGV;
    
    open(FILE, ">", $fname) or die "Can't open $fname for writing ($!)";
    
    my $minimum = 32;
    my $range = 96;
    
    for (1 .. $num_bytes) {
        print FILE pack( "c", int(rand($range)) + $minimum);
    }
    
    close(FILE);
    

    当我真的需要二进制文件时,我使用pack("c")chr() 也可能没问题,但 IIRC 它实际上取决于您的环境使用的字符编码(想想 ASCII 与 utf8。)

    顺便说一句,如果您确实需要二进制文件以兼容 Windows,您可能需要在 open 之后添加 binmode FILE;

    否则,如果范围是可选的,您可以简单地使用dd if=/dev/random of=$filename bs=1 count=$size_of_the_output(或者在 Linux 上更快的加密不安全/dev/urandom)。但这会慢得多,因为/dev/random 真的试图提供真正的随机位——因为它们变得可用。如果它们不够多(例如,您的平台没有 H/W RNG),那么性能真的会受到影响 - 与速度极快的 libc 的伪随机数生成器相比(Perl 在内部使用来实现 rand()) .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      • 2015-12-19
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 2018-06-19
      • 1970-01-01
      相关资源
      最近更新 更多