Есть ли более эффективный способ создания случайного файла в Perl? - PullRequest
6 голосов
/ 10 августа 2010

Это мой первый скрипт на 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);

Его цель - создать файл указанного размера, заполненный случайными символами .

Работает, но довольно медленно.Запись случайного файла размером 10 МБ занимает несколько секунд.
У кого-нибудь есть предложения / советы, как сделать его быстрее / лучше?Также не стесняйтесь указывать на распространенные ошибки новичка.

Ответы [ 3 ]

6 голосов
/ 10 августа 2010
  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;
}
5 голосов
/ 10 августа 2010

Запись потоковых данных из /dev/random.

#!/usr/bin/perl
use File::Copy;
if ($#ARGV < 1) { die("usage: <size_in_bytes>\n"); }
copy("/dev/random","tmp", $ARGV[0]) or die "Copy failed: $!";

код не проверен.

Edit: Так как вы хотите диапазон, сделайте это.

Ваш диапазон составляет от 96 до 32, что составляет 64. 64 = 01000000b (0x40 в шестнадцатеричном формате). Просто сгенерируйте свои числа и преобразуйте побитовое И против числа, которое является диапазоном значений, которые будут сгенерированы-1, и добавьте нижнюю границу, предварительно сформировав побитовое ИЛИ со значением (00100000b или 0x20)

Это позволит вам делать такие вещи, как брать любую случайную строку (просто читать необработанные шестнадцатеричные значения из / dev / random) и преобразовывать данные в ваш диапазон.

1 голос
/ 10 августа 2010

Если вам нужны случайные числа из диапазона, я не знаю более эффективного способа. Ваш сценарий адаптирован к моим предпочтениям:

#!/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, вы можете добавить binmode FILE; после open.

В противном случае, если диапазон является необязательным, вы можете просто dd if=/dev/random of=$filename bs=1 count=$size_of_the_output (или в Linux более быстрая крипто-небезопасная /dev/urandom). Но это будет намного медленнее, поскольку /dev/random действительно пытается доставлять реальные случайные биты - по мере их появления. И если их недостаточно (например, на вашей платформе нет H / W RNG), производительность действительно пострадает - по сравнению с невероятно быстрым генератором псевдослучайных чисел libc (Perl использует внутренне для реализации rand()) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...