Perl сохранить UTF-8 текстовой проблемы - PullRequest
0 голосов
/ 29 июня 2011

Я играю вокруг pplog, одного блога с файловой базой.

Запись в код файла:

open(FILE, ">$config_postsDatabaseFolder/$i.$config_dbFilesExtension");

my $date = getdate($config_gmt);
print FILE $title.'"'.$content.'"'.$date.'"'.$category.'"'.$i;    # 0: Title, 1: Content, 2: Date, 3: Category, 4: FileName
print 'Your post '. $title.' has been saved. <a href="?page=1">Go to Index</a>';
close FILE;

Вводимый текст:

春眠不覺曉,處處聞啼鳥. 夜來風雨聲,花落知多小.

После сохранения в файл он становится:

春眠不覺�›�,處處聞啼鳥.  夜來風�›�聲,花落知多小.

Я могу использовать Eclipse, чтобы отредактировать файл и сделать его нормальным.Проблема существует во время печати в файл.

Некоторая базовая информация: Strawberry Perl 5.12 без использования utf8;попробовал использовать utf8 ;, не имеет эффекта.

Спасибо.

--- EDIT --- Спасибо за комментарии.Я проследил код:

Коды добавления нового контента:

# Blog Add New Entry Page

    my $pass = r('pass');


        #BK 7JUL09 patch from fedekun, fix post with no title that caused zero-byte message...  
        my $title = r('title');
        my $content = '';
        if($config_useHtmlOnEntries == 0)
        {
            $content = bbcode(r('content'));
        }
        else
        {
            $content = basic_r('content');
        }
        my $category = r('category');
        my $isPage = r('isPage');

sub r
{
    escapeHTML(param($_[0]));
}

sub r перенаправляет команду в функцию CGI.pm.

В CGI.pm

sub escapeHTML {
     # hack to work around  earlier hacks
     push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
     my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
     return undef unless defined($toencode);
     $toencode =~ s{&}{&amp;}gso;
     $toencode =~ s{<}{&lt;}gso;
     $toencode =~ s{>}{&gt;}gso;
     if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML 3\.2/i) {
     # $quot; was accidentally omitted from the HTML 3.2 DTD -- see
     # <http://validator.w3.org/docs/errors.html#bad-entity> /
     # <http://lists.w3.org/Archives/Public/www-html/1997Mar/0003.html>.
        $toencode =~ s{"}{&#34;}gso;
     }
     else {
        $toencode =~ s{"}{&quot;}gso;
     }

    # Handle bug in some browsers with Latin charsets
    if ($self->{'.charset'} 
            && (uc($self->{'.charset'}) eq 'ISO-8859-1'    # This line cause trouble. it treats Chinese chars as ISO-8859-1
            || uc($self->{'.charset'}) eq 'WINDOWS-1252')) {
                $toencode =~ s{'}{&#39;}gso;
                $toencode =~ s{\x8b}{&#8249;}gso;
                $toencode =~ s{\x9b}{&#8250;}gso;
        if (defined $newlinestoo && $newlinestoo) {
            $toencode =~ s{\012}{&#10;}gso;
            $toencode =~ s{\015}{&#13;}gso;
        }
    }
    return $toencode;
}

Далее проследить проблему, обнаружив в браузере значение по умолчанию iso-8859-1, даже вручную установив utf-8, отправляет строку обратно всервер как iso-8859-1.

Наконец,

print header(-charset => qw(utf-8)), '<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />

добавить параметр -charset => qw (utf-8) в заголовок.Китайское стихотворение - это все еще китайское стихотворение.

Спасибо за комментарии Шверна, это вдохновило меня на то, чтобы отследить проблему и выучить leeson.

Ответы [ 3 ]

2 голосов
/ 29 июня 2011

Для того, чтобы UTF8 действительно работал в Perl, нужно включить множество отдельных функций.use utf8 только делает ваш код utf8 (строки, переменные, регулярные выражения ...), вы должны делать файловые дескрипторы отдельно.

Его сложно, и самое простое - использовать utf8 :: all, что сделает utf8 значением по умолчанию для вашего кода, ваших файлов, @ARGV, STDIN, STDOUT и STDERR.Поддержка utf8 постоянно улучшается в Perl, и utf8 :: all будет добавлять ее по мере доступности.

0 голосов
/ 29 июня 2011

Вы не показываете код, который на самом деле работает.Я успешно обработал текст, который вы указали в качестве ввода в 5.10.1 для Cygwin и 5.12.3 для Windows.Так что я подозреваю ошибку в вашем коде.Попробуйте сузить проблему, написав короткий самостоятельный тестовый пример.

0 голосов
/ 29 июня 2011

Я не уверен в том, как ваш код может генерировать этот вывод - например, кавычки отсутствуют. Конечно, это может быть связано с «повреждением» где-то между вашим файлом и тем, что я вижу страницу. ТАК может фильтровать испорченный UTF-8. Я предлагаю предоставлять гекс-дампы в будущем!

В любом случае, чтобы заставить вывод UTF-8 работать в Perl, есть несколько подходов:

  1. Работа с символьными данными, то есть Perl знает, что ваши переменные содержат Unicode. Это, наверное, лучший метод. Подтвердите, что utf8::is_utf8($var) верно (вам не нужно , а не должно use utf8 для этого). Если нет, посмотрите на функцию decode модуля Encode, чтобы Perl знал свой Unicode. Как только Perl узнает, что ваши данные являются символами, эта печать выдаст предупреждения (которые вы включили, верно?). Чтобы исправить, включите слой :utf8 или :encoding(utf8) в вашем файле (последняя версия обеспечивает проверку ошибок). Вы можете сделать это в вашем open (open FILE, '>:utf8', "$fname") или, альтернативно, включить его с помощью binmode (binmode FILE, ':utf8'). Обратите внимание, что вы также можете использовать другие кодировки; см. encoding и PerlIO::encoding документы.

  2. Рассматривайте ваш Unicode как непрозрачные двоичные данные. utf8::is_utf8($var) должно быть ложным. Вы должны быть очень осторожны при работе со строками; например, если у вас есть UTF-16-BE, это будет плохой идеей: print "$data\n", потому что вам действительно нужно print $data\0\n". UTF-8 имеет меньше таких проблем, но вы должны знать о них.

Я предлагаю прочитать справочные руководства / стручки perluniintro, perlunitut, perlunicode и perlunifaq.

Кроме того, use utf8; просто сообщает Perl, что ваш скрипт написан на UTF-8. Его эффекты очень ограничены; см. его документы под.

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