2010-07-22 2 views
3

У меня есть текстовые файлы, которые я пытаюсь преобразовать с помощью Perl-скрипта в Windows. Текстовые файлы выглядят нормально в Notepad +, но все регулярные выражения в моем скрипте не совпадают. Затем я заметил, что когда я открываю текстовые файлы в NotePad +, в строке состояния говорится «UCS-2 Little Endia» (sic). Я предполагаю, что это соответствует кодировке UCS-2LE. Так что я создал «ReadFile» и «WriteFile» подлодку в Perl, например, так:Unicode в 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 + ошибается в кодировании? Как мне продолжить?

+0

Предоставлять тестовые данные, дополнительные шестнадцатеричное этого является хорошей идеей. Покажите * полный * код, который вызывает проблему. Если вы не позволите нам воспроизвести проблему, мы можем только предполагать. – daxim

+0

@ daxim: код здесь достаточно полный, единственная причина, по которой я не могу проверить это, потому что у меня нет редактора блокнота +. Угадайте, это проблема спецификации. – 2010-07-22 08:00:59

ответ

2

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

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

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

binmode по-видимому, имеет понятие «слоистый» I/O что несколько сложно.

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

(я добавил это как отдельный вопрос: CRLF translation with Unicode in Perl)

1

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

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

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

Смежные вопросы