Проблемы чтения двоичного файла с ActivePerl? - PullRequest
3 голосов
/ 17 августа 2010

Я пытаюсь прочитать двоичный файл со следующим кодом:

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;

Входной файл 16M; Debug.txt только около 400 КБ. Когда я смотрю на debug.txt в emacs, последние два символа - это ^ A ^ C (символы SOH и ETX, согласно notepad ++), хотя этот же шаблон присутствует в debug.txt. Следующая строка в файле содержит символ ^ O (SI), и я думаю, что это первое вхождение этого конкретного символа.

Как я могу прочитать весь этот файл?

Ответы [ 3 ]

5 голосов
/ 17 августа 2010

Если вы действительно хотите прочитать весь файл сразу, используйте режим slurp.Режим Slurp можно включить, установив $/ (который является разделителем входной записи) на undef.Лучше всего это сделать в отдельном блоке, чтобы не испортить $/ для другого кода.

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;

Используйте my $data для лексического и our $data для глобальной переменной.

3 голосов
/ 17 августа 2010

TIMTOWTDI .

File::Slurp - самый короткий способ выразить то, чего вы хотите достичь. Он также имеет встроенную проверку ошибок.

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

API 1012 *IO::File решает проблему глобальной переменной $/ более элегантным способом.

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);
}
0 голосов
/ 31 октября 2013

Я не думаю, что речь идет об использовании режима slurp или нет, а о правильной обработке бинарных файлов.

вместо

$data = <F>;

вы должны сделать

read(F, $buffer, 1024);

Это будет считывать только 1024 байта, поэтому вы должны увеличить буфер или прочитать всю часть файла по частям, используя цикл.

...