Perl:文本连接后编码搞砸了

时间:2010-03-03 15:16:37

标签: perl encoding concatenation

我在更新/升级某些遗留代码时遇到了一种奇怪的情况。

我有一个包含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加载的值尝试了Encode函数,但无济于事。根据“凯特”,文件本身似乎是utf8。

除此之外,我有另一个具有相同行为的函数,它使用完全相同的函数,值和文件。从Perl / Apache启动调用时,编码正常。通过AJAX再次,它搞砸了。

我一直在检查AJAX请求(jQuery)并且找不到任何奇怪的东西。编码似乎也是utf8。

3 个答案:

答案 0 :(得分:4)

Perl的每个标量值都有一个“utf8”标志,可以是“开”或“关”。标志的“On”状态告诉perl将值视为Unicode字符串。

如果你取一个带有utf8标志的字符串并将其与一个打开了utf8标志的字符串连接起来,perl会将第一个字符串转换为Unicode。这是问题的常见原因。

在连接之前,您需要将两个变量转换为Encode::encode()的字节或转换为perl的内部格式{。}}。

perldoc Encode

答案 1 :(得分:2)

扩展上一个答案,这里有一些我发现有用的信息,当我开始搞乱Perl中的字符编码时。

这是perl中对Unicode的出色介绍:http://perldoc.perl.org/perluniintro.html。 “Perl的Unicode模型”部分与您所看到的问题特别相关。

在Perl中使用的一个好规则是将数据解码为Perl字符,并在其出路时将其编码为字节。您可以使用Encode::encodeEncode::decode明确执行此操作。如果您正在读取/写入文件句柄,则可以使用binmode并设置图层来指定文件句柄的编码:perldoc -f binmode

您可以使用Encode::is_utf8判断示例中的哪些字符串已被解码为Perl字符:

use Encode qw( is_utf8 );
print is_utf8($stuff) ? 'characters' : 'bytes';

答案 2 :(得分:0)

我的一位同事找到了这个问题的答案。它确实与AJAX启动呼叫的事实有关。

文件结构如下:

1个处理程序,由Apache访问 1个处理程序,由Apache访问但只包含AJAX响应程序。我们称之为AJAX-Handler
1个包,其中包含与整个软件相关的功能,他们访问我们自己的Framework中的其他包

在AJAX-Handler内部,我们打印结果

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

现在,当我将$r->print($output);替换为print($output);时,问题就会消失!我知道这不是在mod_perl中打印东西的推荐方法,但这似乎有效。

尽管如此,欢迎任何有关如何以正确方式做到这一点的想法。