0

我正在玩 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 without use utf8;尝试使用 utf8;,没有效果。

谢谢你。

--- 编辑 --- 感谢您的评论。我追踪了代码:

代码添加新内容:

# 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) 参数添加到标题中。中国诗还是中国诗。

感谢 Schwern 的评论,它启发了我去追查问题并学习 leeson。

4

3 回答 3

2

为了让 utf8 真正在 Perl 中工作,需要翻转许多单独的特性。 use utf8仅使您的代码为 utf8(字符串、变量、正则表达式...),您必须单独处理文件。

它很复杂,但最简单的是使用utf8::all,这将使 utf8 成为您的代码、文件、@ARGV、STDIN、STDOUT 和 STDERR 的默认值。Perl 中对 utf8 的支持不断改进,并且 utf8::all 将在可用时添加它。

于 2011-06-29T18:54:43.203 回答
0

您没有显示实际运行的代码。我使用 Cygwin 上的 5.10.1 和 Windows 上的 5.12.3 成功处理了您作为输入提供的文本。所以我怀疑你的代码中存在错误。尝试通过编写一个简短的、独立的测试用例来缩小问题的范围。

于 2011-06-29T19:24:04.187 回答
0

我不确定您的代码如何产生该输出——例如,缺少引号。当然,这可能是由于您的文件和我看到该页面之间的某处“损坏”。SO 可能会过滤损坏的 UTF-8。我建议将来提供十六进制转储!

无论如何,要让 UTF-8 输出在 Perl 中工作,有几种方法:

  1. 使用字符数据,即让 Perl 知道您的变量包含 Unicode。这可能是最好的方法。确认这utf8::is_utf8($var)是真的(您不需要也不应该这样 use utf8做)。如果没有,请查看Encode模块的decode函数以使 Perl 知道它的 Unicode。一旦 Perl 知道您的数据是字符,该打印将给出警告(您确实启用了,对吗?)。要修复,请在文件上启用:utf8or:encoding(utf8)层(后一个版本提供错误检查)。您可以在 open ( open FILE, '>:utf8', "$fname") 中执行此操作,或者使用 binmode ( binmode FILE, ':utf8') 启用它。请注意,您也可以使用其他编码;请参阅encodingPerlIO::encoding文档。

  2. 将您的 Unicode 视为不透明的二进制数据。utf8::is_utf8($var)一定是假的。操作字符串时必须非常小心;例如,如果您有 UTF-16-BE,这将是一个坏主意:print "$data\n",因为您实际上需要print $data\0\n". UTF-8 的此类问题较少,但您需要注意它们。

我建议阅读 perluniintro、perlunitut、perlunicode 和 perlunifaq 手册页/pod。

此外,use utf8;只需告诉 Perl 您的脚本是用 UTF-8 编写的。它的作用非常有限;查看它的 pod 文档。

于 2011-06-29T16:23:32.890 回答