2013-09-08 2 views
1

У меня есть приложение в Perl/CGI, где я получаю файл utf8 txt и обрабатываю его содержимое.Perl распознает utf8 как Unicode после 4096 байт

По какой-то причине (я думаю, что Perl делит файл на 4096 байт буфера, и только первый имеет знак байтового заказа). Perl интерпретирует содержимое файла как Unicode после 4096 байт.

Если я распространил некоторые дефисы («-») в середине файла (по крайней мере один для каждого блока из 4k), программа распознает его как utf8, возможно, потому, что Unicode не имеет дефиса.

Я получаю TXT из HTML страницы и отправить его в скалярной переменной, как это:

while(my $l = <$fh>){ 
    $text .= $l; 
} 

Я пытался заставить utf8 конкатенацией каждую строку файла с тире:

while(my $l = <$fh>){ 
    $text .= "–".$l; 
} 

Но я получаю эту ошибку:

Wide character in print at (eval 12) line 94. 

ли кто-нибудь есть совет? имеет Спасибо!

+1

"Unicode не имеют отдельные черточки". Это неверно. http://www.fileformat.info/info/unicode/char/2013/index.htm –

ответ

3

Perl может работать с кодами Unicode, но все операции ввода-вывода выполняются с байтами. Когда вы печатаете строку с высокими кодовыми точками в обычный дескриптор файла, вы получаете предупреждение «широкий символ в печати».

Вы должны декодировать все входные данные, и encode весь ваш выход. Лучший способ сделать это - использовать уровни PerlIO. Вы можете добавить слои с помощью binmode. Например:

use utf8; # This source file is encoded in UTF-8. 
      # Else, the literal "–" would be seen as multiple bytes, not one single character. 

binmode STDOUT, ":uft8"; # encode all strings (that get printed to STDOUT) 
         # to the binary UTF-8 representation 
print "–\n"; # EN DASH – works. 

При открытии файла вы можете добавлять уровни PerlIO в открытом режиме, например.

open my $fh "<:utf8", $filename or die ...; 

Это прозрачно преобразует двоичный вход в кодовые точки.

Не объединяйте байтовые строки, которые содержат двоичный UTF-8 с правильно декодированными строками - результат скорее всего будет недействительным. Конечно, такие проблемы не возникают при декодировании всего ввода.

Способ буферов Perl ввода не должен влиять на вашу программу; вероятно, вы неправильно определили это. Perl не выполняет обнаружение кодирования через спецификации на входных файлах.

В контексте веб-программирования, кодирующая свой вывод, как UTF-8 является хорошим выбором, но не забудьте также установить charset свойство в заголовках ответа:

Content-Type: text/html; charset=UTF-8 

HTML-документ следует подтвердить это с <meta charset="UTF-8">.

+0

Привет, спасибо за ответ. Что вы подразумеваете под «печать строки с высокими кодовыми точками в обычный дескриптор файла»?У меня уже есть «широкий символ в печати», предупреждающий еще раз и никогда не понимал этого по-настоящему. Каждый раз, когда я открываю файл с диска, я использую: open FH, "<: encoding (UTF-8)"; И все идет нормально. Но как я мог это сделать, как только CGI даст мне всего $ fh? – gvieira

+0

@gvieira Это хорошо, но вам также нужно кодировать данные при печати. Это можно сделать с помощью «binmode STDOUT»: utf8 «' (или любого дескриптора файла и кодировки, который вы хотите). Тогда это предупреждение должно исчезнуть. Высокой точкой кода является любой символ, не являющийся латинским-1 (IIRC). – amon

+0

@gvieira Этот ответ был написан до вашего редактирования. Вам нужно добавить слой ': utf8' (или эквивалентный уровень) как для ввода, так и для дескриптора выходного файла. В обоих случаях слои могут быть добавлены с помощью 'binmode', как показано. – amon

0

Try:

use Encode qw(encode); 

$text = join '', <$fh>; 

$text = encode("utf8", $text); 
Смежные вопросы