Problemas de lectura de un archivo binario con ActivePerl?
-
29-09-2019 - |
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?
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
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.