Unicode в Perl не работает - PullRequest
3 голосов
/ 22 июля 2010

У меня есть несколько текстовых файлов, которые я пытаюсь преобразовать с помощью Perl-скрипта в Windows. В Notepad + текстовые файлы выглядят нормально, но все регулярные выражения в моем сценарии не совпадают. Затем я заметил, что когда я открываю текстовые файлы в NotePad +, в строке состояния появляется надпись «UCS-2 Little Endia» (sic). Я предполагаю, что это соответствует кодировке UCS-2LE. Поэтому я создал подпрограммы "readFile" и "writeFile" в Perl, вот так:

use PerlIO::encoding;

my $enc = ':encoding(UCS-2LE)';

sub readFile {
    my ($fName) = @_;
    open my $f, "<$enc", $fName or die "can't read $fName\n";
    local $/;
    my $txt = <$f>;
    close $f;
    return $txt;
}

sub writeFile {
    my ($fName, $txt) = @_;
    open my $f, ">$enc", $fName or die "can't write $fName\n";
    print $f $txt;
    close $f;
}

my $fName = 'someFile.txt';

my $txt = readFile $fName;
# ... transform $txt using s/// ...
writeFile $fName, $txt;

Теперь регулярные выражения совпадают (хотя и реже, чем я ожидаю), но вывод содержит длинные строки азиатских символов, перемежающиеся с длинными строками правильного текста. Мой код неверен? Или, возможно, Notepad + не так с кодировкой? Как мне поступить?

Ответы [ 2 ]

2 голосов
/ 23 июля 2010

ОК, я понял это. Проблема была вызвана разрывом между переводом кодировки, выполняемым параметром «encoding ...» вызова «open», и переводом CRLF по умолчанию, выполняемым Perl в Windows. Казалось, что происходило то, что LF переводился в CRLF на выходе после , кодирование уже было сделано, что отбрасывало «четность» 16-битного кодирования для следующей строки. Как только следующая линия была достигнута, «паритет» был возвращен. Это объясняет «длинные строки азиатских символов, перемежающиеся с длинными строками правильного текста» ... каждая другая строка была испорчена.

Чтобы исправить это, я вынул параметр кодирования в моем вызове «open» и добавил вызов «binmode» следующим образом:

open my $f, $fName or die "can't read $fName\n";
binmode $f, ':raw:encoding(UCS-2LE)';

binmode , очевидно, имеет концепцию "многоуровневой" обработки ввода / вывода, которая несколько сложна.

Одна вещь, которую я не могу понять, это как вернуть мой перевод CRLF. Если я опускаю: raw или add: crlf, проблема «четности» возвращается. Я также попробовал сделать повторный заказ и не могу заставить его работать.

(я добавил это отдельным вопросом: Перевод CRLF с Unicode в Perl )

1 голос
/ 22 июля 2010

У меня нет редактора Notepad + для проверки, но это может быть проблемой спецификации, если ваша выходная кодировка не содержит спецификации.

http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM

Возможно, вам нужно кодировать $ txt, используя метку порядка байтов, как описано выше.

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