Pregunta

Estoy intentando leer un archivo binario con el siguiente código:

open(F, "<$file") || die "Can't read $file: $!\n";
binmode(F);
$data = <F>;
close F;

open (D,">debug.txt");
binmode(D);
print D $data;
close D;

El archivo de entrada es de 16 millones; la debug.txt es de sólo 400k. Cuando miro debug.txt en emacs, los dos últimos caracteres son ^ A ^ C (SOH y ETX caracteres, de acuerdo con el bloc de notas ++), aunque el mismo patrón está presente en la debug.txt. La siguiente línea en el archivo tiene un ^ O (SI) char, y yo creo que es la primera aparición de ese personaje en particular.

¿Cómo puedo leer en todo este archivo?

¿Fue útil?

Solución

Si realmente quiera leer todo el archivo a la vez, utilice el modo cómo sorber. Slurp modo se puede activar mediante el establecimiento de $/ (que es el separador de registro de entrada) a undef. Esto se realiza mejor en un bloque separado para que no se metan hasta $/ de otro código.

my $data;
{
    open my $input_handle, '<', $file or die "Cannot open $file for reading: $!\n";
    binmode $input_handle;
    local $/;
    $data = <$input_handle>;
    close $input_handle;
}

open $output_handle, '>', 'debug.txt' or die "Cannot open debug.txt for writing: $!\n";
binmode $output_handle;
print {$output_handle} $data;
close $output_handle;

Uso my $data para un léxico y our $data para una variable global.

Otros consejos

TIMTOWTDI .

File::Slurp es el camino más corto para expresar lo que quiere lograr. También se ha incorporado en la comprobación de errores.

use File::Slurp qw(read_file write_file);
my $data = read_file($file, binmode => ':raw');
write_file('debug.txt', {binmode => ':raw'}, $data);

El IO::File API resuelve el problema variable de $/ mundial de una manera más elegante.

use IO::File qw();
my $data;
{
    my $input_handle = IO::File->new($file, 'r') or die "could not open $file for reading: $!";
    $input_handle->binmode;
    $input_handle->input_record_separator(undef);
    $data = $input_handle->getline;
}
{
    my $output_handle = IO::File->new('debug.txt', 'w') or die "could not open debug.txt for writing: $!";
    $output_handle->binmode;
    $output_handle->print($data);
}

No creo que esto es acerca de la modalidad slurp o no, sino de manejar correctamente los archivos binarios.

en lugar de

$data = <F>;

que debe hacer

read(F, $buffer, 1024);

Esto sólo va a leer 1024 bytes, así que hay que aumentar la memoria intermedia o leer toda la parte de archivos por parte usando un bucle.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top