2010-08-10 12 views
6

Este es mi primer script de Perl. Nunca:¿Existe alguna forma más eficiente de generar un archivo aleatorio en 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); 

Su propósito es generate a file in a specified size filled with random characters.

Funciona, pero es bastante lento. Lleva unos segundos escribir un archivo aleatorio de 10MB.
¿Alguien tiene sugerencias/consejos sobre cómo hacerlo más rápido/mejor? También siéntase libre de señalar los errores comunes de los principiantes.

Respuesta

6
  1. Puede solicitar rand para crear más de un valor para usted cada vez que lo llame.
  2. Recopila varios caracteres juntos antes de llamar al print. Imprimir un caracter a la vez es ineficiente.

 

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; 
} 
+1

I * think * perl funciona mejor en 4k fragmentos enviados a la transmisión. Relacionado SO para cambiar el tamaño del búfer de la secuencia: http://stackoverflow.com/questions/1251062/how-can-i-set-the-file-read-buffer-size-in-perl-to-optimize-it-for -grandes archivos – Incognito

+0

¿Por qué usas 'my $ rand = int (rand ($ range ** 4))' y 'chr ($ rand% $ range + $ minimum)' en lugar de solo 'my $ rand = int (rand ($ range) 'y' chr ($ rand + $ minimum) '? – Alexander

+0

' rand ($ range ** 4) 'contiene suficiente información para generar 4 caracteres aleatorios – mob

4

Escribir datos de transmisión desde/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: $!"; 

código no probado.

Editar: Ya que desea un rango, haga esto.

Su rango está entre 96 y 32, que es un espacio de 64. 64 = 01000000b (0x40 en hexadecimal). generar simplemente sus números y la preforma de un bit a bit y contra el número que es el rango de valores que se genere-1 y añadir el límite inferior formando previamente un OR con su valor (00100000b, o 0x20)

Esto le permitirá haces cosas como tomar cualquier cadena aleatoria (solo leer el hexágono crudo de/dev/aleatorio) y transformar los datos para que estén dentro de tu rango.

+1

que quiere decir/dev/random, probablemente. Tenga en cuenta que solo se trata de sistemas unix. –

+0

Sí, gracias por detectar eso. Apuesto a que está en Unix en función de dónde se encuentra Perl (usr/bin) – Incognito

+0

Esto no me permite controlar qué caracteres se escriben o no. – quantumSoup

1

Si necesita números aleatorios de un rango, no conozco la manera más eficiente. La secuencia de comandos ajusta a mis aficiones:

#!/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); 

utilizo pack("c") cuando realmente lo necesito binario. chr() podría ser muy bien también, pero IIRC en realidad depende de lo que el juego de caracteres que está utilizando el medio ambiente (creo ASCII vs utf8.)

Por cierto si realmente necesita el archivo binario para la compatibilidad de Windows es posible que desee añadir binmode FILE; después de la open .

De lo contrario, si el rango es opcional, puede simplemente dd if=/dev/random of=$filename bs=1 count=$size_of_the_output (o en Linux, el cifrado inseguro más rápido /dev/urandom). Pero eso sería mucho más lento ya que /dev/random realmente intenta entregar bits aleatorios reales, a medida que estén disponibles. Y si no hay suficientes (por ejemplo, su plataforma no tiene H/W RNG), el rendimiento realmente sufrirá, en comparación con el generador de números pseudoaleatorios de la libc sorprendentemente rápida (Perl lo usa internamente para implementar el rand()).

Cuestiones relacionadas