如何在Perl中将带重音和其他外语字符编码为UTF8

5

我已经到处尝试学习和理解这个问题,但我一无所获。

让我们来看一个字符串:

夹心饼干杏仁蛋糕。糖李子曲奇杏仁蛋卷棒棒糖布朗尼提拉米苏羊角面包。薄脆饼干冰淇淋巧克力棒软糖。芝士蛋糕粉末夹心糖果。甜甜圈糕点糖果拐杖。甘草牛轧糖糖果拐杖果冻。芝麻脆饼干杏仁擦餅李子杯形蛋糕苹果派。巧克力冰激凌棉花糖舒芙蕾。苹果派丹麦面包unerdwear.com薄脆饼干unerdwear.com杏仁蛋糕布丁。果冻棉花糖布朗尼棒棒糖杏仁蛋糕甜卷胡萝卜蛋糕巧克力棒。塔形糖果拐杖曲奇unerdwear.com软糖粉末。果冻半夜苹果派布丁牛轧糖杏仁糖。杏仁糖果果酱派粉末糖衣。软糖果冻提拉米苏熊掌布朗尼芝士蛋糕。糖衣批萨燕麦蛋糕棒棒糖胡萝卜蛋糕太妃糖。甜甜圈果酱李子杏仁蛋糕。水果蛋糕提拉米苏棉花糖果饼塔形果酱。Unerdwear.com 杏仁糖果 unerdwear.com蜜糖熊软糖糖豆布朗尼夹心饼干。杏仁糖果果冻甜甜圈棉花糖棉花糖甜甜圈。舒芙蕾薄脆饼干糖果拐杖胡萝卜蛋糕。芝士蛋糕松饼粉末软糖胡萝卜蛋糕。芝麻糖浆冰淇淋夹心饼干甜甜圈苹果派杯形蛋糕。蛋糕糖衣甘草。糖李子脆饼干杏仁糖豆。胡萝卜蛋糕糖果拐杖甜糖果。糖拐杖杏仁糖霜软糖丹麦蛋糕布朗尼曲奇燕麦蛋糕。

当我执行:

Encode::encode('UTF-8', $text);

在这个字符串中,单词Soufflé被编码成了Soufflé。

看到这个,我不认为它是任何代码点或任何有效的编码映射(即é)。我怎么能指望它以一种可以正确阅读的方式到达目的地?换句话说,为什么Perl给我返回é而不是我已经将其编码为UTF8并且应该给我é的结果?

xmlbody($text);

sub xmlbody {
    $description = shift;

    use XML::Writer;
    my $writer = XML::Writer->new( OUTPUT => 'self', ENCODING => 'utf-8' );
    my $writer->xmlDecl('utf-8');

    ## ...structure

    $writer->cdataElement('description',$description);

    ## ...more structure

    $writer->end();
}

use utf8; 看起来没有对上述字符串中的特殊字符进行编码,仍然显示为“é”。如果我不使用文件句柄或stdin/stdout,那么使用$writer->xmlDecl('utf-8')是否相当于use open qw(:std :utf8)


2
你不应该直接使用Encode模块!通过 use utf8 声明你的源代码为utf8编码, 然后通过 use open qw(:std :utf8) 声明输出为utf8编码。如果你想将非ASCII字符转换为XML实体,则需要进行另外的处理。 - tchrist
@tchrist 很有趣,我在我工作的一些代码中到处看到它的使用。我的问题是发送用 CDATA 标记编码的文本。我没有提及这一点的原因是我认为错误更多是本地于我的 Perl 代码。 - a7omiton
2
好的,很难说你上面的字符串例子是从哪里来的。如果它是你程序中的字符串字面量,那么你需要在该源单元/文件中使用use utf8。如果它来自于程序外部,你需要在该流上设置编码。如果它来自其他地方,比如参数、环境变量或数据库,那么你就需要做一些处理。 - tchrist
@tchrist 我在这里提供了一个简短的示例,以确保我的 XML 中的字符使用 UTF-8 进行编码,但在尝试编码 é 时却给我返回了 é 字符。 - a7omiton
@tchrist,这将会给你同样的问题,即双重编码。XML::Writer已经对输出进行了编码(正如它应该做的那样)。 - ikegami
1个回答

2
当我查看这个时,我无法将其识别为任何代码点或有效的编码映射。
如果您查看fileformat.info上的相关页面,您将看到正在发生的事情。
最初,在您的程序中,您有一个Unicode字符“é”。该字符的Unicode字符代码为U + 00E9。当您将该字符编码为UTF-8时,您会得到一个由两个字节组成的字符 - 0xC3 0xA9。如果您查看{{link2:ISO-8859-1的代码页}},您将看到0xC3为“Ô,0xA9为“©”。
如果您尝试在理解UTF-8并期望UTF-8的设备上显示该双字节字符,则会显示“é”。否则,设备将使用其本地字符编码(可能是ISO-8859-1),您将看到您所看到的Mojibake
正如 tchrist 所说,处理这个问题最简单的方法是使用 Perl 的工具,它们会自动为你处理,无需考虑。

非常棒的解释,让我更加清晰地理解了。感谢您的帮助。 - a7omiton
在 Perl 中,不要将字符串表达式视为字面量。 - MUY Belgium

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接