Самый простой способ - использовать двоичный ввод-вывод для всего. Таким образом, нам не нужно беспокоиться о переключении режимов файлов на полпути, и в Unix в любом случае нет никакой разницы между текстовым и двоичным режимом (за исключением случаев, когда речь идет о кодировках, но здесь мы просто хотим копировать байты без изменений).
В зависимости от того, насколько велика текстовая часть файла, мы можем либо обрабатывать ее построчно, либо сразу читать все в память.
#!/usr/bin/perl
use strict;
use warnings;
my ($inputfilename, $outtextfilename, $outbinfilename) = @ARGV;
open my $in_fh, '<:raw', $inputfilename
or die "$0: can't open $inputfilename for reading: $!\n";
open my $out_txt_fh, '>:raw', $outtextfilename
or die "$0: can't open $outtextfilename for writing: $!\n";
open my $out_bin_fh, '>:raw', $outbinfilename
or die "$0: can't open $outbinfilename for writing: $!\n";
# process text part
while (my $line = readline $in_fh) {
print $out_txt_fh $line;
last if $line =~ m{</FileSystem>};
}
# process binary part
while (read $in_fh, my $buffer, 4096) {
print $out_bin_fh $buffer;
}
В этой версии кода построчно обрабатывается текстовая часть, а двоичная часть - кусками по 4096 байт (без учета внутренней буферизации).
В качестве альтернативы, если последовательность символов, отмечающая конец текстовой части, точно равна "</FileSystem>\n"
, мы можем быть немного дерзкими:
# process text part
{
local $/ = "</FileSystem>\n";
if (my $line = readline $in_fh) {
print $out_txt_fh $line;
}
}
Мы временно переключаем маркер конца строки с "\n"
на "</FileSystem>\n"
и читаем одну «строку», которая охватывает всю текстовую часть. Это предполагает, что текстовая часть достаточно мала, чтобы удобно помещаться в памяти. Остальная часть сценария такая же.