Perl: кодировка испортилась после объединения текста - PullRequest
2 голосов
/ 03 марта 2010

Я столкнулся со странной ситуацией при обновлении / обновлении устаревшего кода.

У меня есть переменная, которая содержит HTML. Прежде чем я смогу вывести его, он должен быть заполнен большим количеством данных. По сути, у меня есть следующее:

for my $line (@lines) {
    $output = loadstuff($line, $output); 
}

Внутри loadstuff() есть следующее

sub loadstuff {
    my ($line, $output) = @_;
    # here the process is simplified for better understanding.
    my $stuff = getOtherStuff($line);
    my $result = $output.$stuff;
    return $result;
}

Эта функция создает страницу, которая состоит из разных областей. Вся область загружается независимо, поэтому есть цикл for.

Проблемы начинаются прямо здесь. Когда я загружаю страницу с нуля (нажимая на ссылку, Perl выполняет и доставляет HTML), все загружается нормально. Всякий раз, когда я загружаю вторую страницу через AJAX для сравнения, этот HTML-код нарушает кодировку.

Я отследил проблему до этой строки my $result = $output.$stuff. До конкатенации $output и $stuff в порядке. Но потом кодировка в $result испортилась.

Кто-нибудь знает, почему конкатенация портит мою кодировку? Пока мы обсуждаем эту тему, почему это происходит только тогда, когда вызов выполняется через AJAX?

Редактировать 1

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

Единственное отличие в данном конкретном случае состоит в том, что текущие значения для страницы сравниваются со старыми (это функция резервного копирования / восстановления). Отсюда все то же самое. Кодировка в переменных (насколько я могу судить) в порядке. Я даже пытался использовать функции кодирования только для значений, загруженных из AJAX, но безрезультатно. По словам Кейт, сами файлы выглядят как utf8.

Кроме того, у меня есть другая функция с таким же поведением, которая использует ТОЧНЫЕ функции, значения и файлы. Когда вызов запускается из Perl / Apache, кодировка в порядке. Через AJAX, опять же, все испорчено.

Я изучал запрос AJAX (jQuery) и не смог найти ничего странного. Кодировка, похоже, тоже utf8.

Ответы [ 3 ]

4 голосов
/ 03 марта 2010

Perl имеет флаг «utf8» для каждого скалярного значения, которое может быть «включено» или «выключено». Флаг «On» указывает Perl обрабатывать значение как строку символов Unicode.

Если вы возьмете строку с отключенным флагом utf8 и объедините ее со строкой, на которой установлен флаг utf8, Perl преобразует первую в Unicode. Это обычный источник проблем.

Вам нужно либо преобразовать обе переменные в байты с Encode::encode(), либо во внутренний формат perl с Encode::decode() до объединения.

См. perldoc Encode .

2 голосов
/ 04 марта 2010

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

Это отличное введение в Unicode в Perl: http://perldoc.perl.org/perluniintro.html. Раздел "Модель Unicode в Perl" особенно важен для проблемы, с которой вы сталкиваетесь.

Хорошее правило для использования в Perl - декодировать данные в символы Perl на входе и кодировать их в байты на выходе. Вы можете сделать это явно, используя Encode::encode и Encode::decode. Если вы читаете / пишете в дескриптор файла, вы можете указать кодировку для дескриптора файла, используя binmode и установив слой: perldoc -f binmode

Вы можете сказать, какая из строк в вашем примере была декодирована в символы Perl, используя Encode::is_utf8:

use Encode qw( is_utf8 );
print is_utf8($stuff) ? 'characters' : 'bytes';
0 голосов
/ 05 марта 2010

Мой коллега нашел ответ на эту проблему. Это действительно было связано с тем, что AJAX начал вызов.

Структура файла выглядит следующим образом:

1 Обработчик, доступный Apache
1 Обработчик, к которому обращается Apache, но который содержит только респонденты AJAX. Мы называем это AJAX-Handler
1 пакет, который содержит функции, относящиеся ко всему программному обеспечению, которые получают доступ к другим пакетам из нашей собственной платформы

Внутри AJAX-обработчика мы печатаем результат как таковой

sub handler {
    my $r = shift; 
    # processing output   
    $r->print($output);
    return Apache2::Const::OK;
}

Теперь, когда я заменяю $r->print($output); на print($output);, проблема исчезает! Я знаю, что это не рекомендуемый способ печати содержимого в mod_perl, но, похоже, это работает.

Тем не менее, любые идеи, как сделать это правильно, приветствуются.

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