Perl: проблема с изменением кодировки в середине чтения файла

Я использую Perl для загрузки некоторых "макро" файлов. Эти макросы, однако, могут быть закодированы в различных кодировках, поэтому существует директива, определенная для пользователей, пишущих свои макросы (т.е.

#encoding iso-8859-2

в начале макроса).

Каждый раз, когда эта директива встречается в макросе, вызывается кодировка установки функции, которая выглядит так:

sub change_encoding {
  my ($file_handle, $encoding) = @_;
  $file_handle->flush();
  binmode($file_handle);           # get rid of IO layers
  binmode($file_handle,":encoding($encoding)");
}

Проблема в том, что когда я читаю макрос, используя стандартные

while($line = <$file_handle>){
  process_macro($line);
}

Я получил сообщения о том, что "utf8 "\xXY"не отображается на Unicode", но только если символы с диакритическими знаками находятся рядом с директивой #encoding. Я попробовал несколько примеров, и мне удалось получить половину строки с кодами \ xXY и другую половину строки с правильно декодированными символами, как здесь:

sub macro5_fn {
  print "\xBElu\xBBou\xE8k\xFD k\xF9\xF2 úpěl ďábelské ódy\n";
}

Если я добавлю больше комментариев перед функцией, все символы в порядке:

sub macro5_fn {
  print "žluťoučký kůň úpěl ďábelské ódy\n";
}

Проще говоря, количество правильно декодированных символов зависит от расстояния этих символов от директивы #encoding, те, которые находятся близко, не декодируются правильно.

Мне кажется, что это проблема Perl и PerlIO (не) очистки буфера. Или я что-то не так делаю?

Спасибо за ответ.

1 ответ

Решение

Проблема в том, что <> читает более одной строки, поэтому следующая строка интерпретируется под старой кодировкой, прежде чем вы когда-либо увидите #encoding директива для нового.

Лучше всего, вероятно, прочитать файл в двоичном режиме и использовать модуль кодирования для декодирования каждой строки из текущей кодировки.

Другие вопросы по тегам