Perl: проблема с изменением кодировки в середине чтения файла - PullRequest
1 голос
/ 15 марта 2011

Я использую 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 Ответ

5 голосов
/ 15 марта 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...