Файлы не имеют понятия линий;они просто потоки байтов.Perl должен запросить количество байтов из файла у ОС и выяснить, где заканчивается строка, чтобы вернуть строку в программу.
Perl может запрашивать по одному байту за раз от ОС доимеет полную строку, но это было бы очень неэффективно.Существует много накладных расходов при выполнении системных вызовов.Таким образом, Perl запрашивает 8 КиБ одновременно.
Затем необработанные данные должны быть декодированы, прежде чем Perl сможет определить, где заканчивается строка, поскольку необработанный 0A
не обязательно указывает на конец строки..
Подобно тому, почему человек не читает из файла по одному байту за раз, запрос декодера о декодировании только следующего символа будет неэффективным.Каждый раз при запуске и остановке декодирования возникают накладные расходы.Таким образом, Perl декодирует все данные, которые он читает, когда он читает.
Так что это означает, что Perl читает и декодирует больше, чем возвращает в программу.
Решениеобрабатывать файл как двоичный (потому что на самом деле это не текстовый файл, если кодировка изменяется по разделам) и выполнять декодирование самостоятельно.
Если вы работаете с однобайтовой кодировкой, такой как cp1252, вы можете продолжитьиспользуя readline
(он же <$fh>
).Однако вместо того, чтобы указывать Perl искать кодовую строку перевода строки (0A
), вам нужно установить $/
для кодировки кодовой точки.Как это бывает, это также 0A
для cp1252, поэтому никаких изменений не требуется.
use Encode qw( decode );
open( my $fh, "<:raw", $qfn )
or die( "Can't open \"$qfn\": $!\n" );
while( <$fh> ) {
$_ = decode( 'cp1252', $_ ); # :encoding(cp1252)
s/\r\n\z/\n/ if $^O eq 'Win32'; # :crlf
print;
last if /Last/;
}
Если вы не использовали однобайтовую кодировку, возможно, вам придется переключиться на использование read
.(Вы можете продолжать использовать readline
для UTF-8 из-за способа, которым он спроектирован.) При использовании read
точное решение зависит от нескольких особенностей (которые относятся к определению, сколько читать и сколько декодировать).