1

我在 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.

有人有小费吗?有 谢谢!

4

2 回答 2

3

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

您应该解码所有输入数据,并对所有输出进行编码。最好的方法是使用 PerlIO 层。您可以使用binmode. 例如:

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">.

于 2013-09-08T01:14:10.127 回答
0

尝试:

use Encode qw(encode);

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

$text = encode("utf8", $text);
于 2013-10-22T08:41:08.680 回答