Perl在4096字节之后将utf8识别为Unicode

时间:2013-09-08 00:44:58

标签: perl unicode utf-8 buffer byte-order-mark

我在Perl / CGI中有一个应用程序,我收到一个utf8 txt文件并对其内容进行处理。

由于某种原因(我认为Perl将文件分为4096字节缓冲区,只有第一个具有字节顺序标记)Perl在4096字节之后将文件内容解释为Unicode。

如果我在文件中间传播一些短划线(“ - ”)(每个4k块至少有一个),程序会将其识别为utf8,可能是因为Unicode没有短划线。

我从html页面收到txt并将其发送到这样的标量变量:

while(my $l = <$fh>){
    $text .= $l;
}

我尝试通过用短划线连接文件的每一行来强制使用utf8:

while(my $l = <$fh>){
    $text .= "–".$l;
}

但是我收到了这个错误:

Wide character in print at (eval 12) line 94.

有人有小费吗? 具有 谢谢!

2 个答案:

答案 0 :(得分:3)

Perl可以在Unicode代码点上运行,但所有I / O都是用字节完成的。当您将具有高代码点的字符串打印到普通文件句柄时,您会收到“打印中的宽字符”警告。

您应解码所有输入数据,编码所有输出。最好的方法是使用PerlIO层。您可以使用binmode添加图层。 E.g:

use utf8; # This source file is encoded in UTF-8.
          # Else, the literal "–" would be seen as multiple bytes, not one single character.

binmode STDOUT, ":uft8"; # encode all strings (that get printed to STDOUT)
                         # to the binary UTF-8 representation
print "–\n"; # EN DASH – works.

打开文件时,可以在打开模式下添加PerlIO图层,例如

open my $fh "<:utf8", $filename or die ...;

这会透明地将二进制输入转换为代码点。

不要将包含二进制UTF-8的字节字符串与正确解码的字符串连接起来 - 结果很可能是无效数据。当然,解码所有输入时不会出现此类问题。

Perl缓冲输入的方式不应该影响你的程序;很可能你误诊了。 Perl不通过输入文件上的BOM进行编码检测。

在Web编程环境中,将输出编码为UTF-8是一个不错的选择,但请确保在响应头中设置charset属性:

Content-Type: text/html; charset=UTF-8

HTML文档应该使用<meta charset="UTF-8">重复此内容。

答案 1 :(得分:0)

尝试:

use Encode qw(encode);

$text = join '', <$fh>;

$text = encode("utf8", $text);