0

我正在 perl 中处理来自 XML 文件的一些数据,并想使用 FIFO File::Queue 来划分和加速该过程。一个 perl 脚本解析 XML 文件并为另一个脚本准备 JSON 输出:

#!/usr/bin/perl -w
binmode STDOUT, ":utf8";
use utf8;
use strict;
use XML::Rules;
use JSON;
use File::Queue;

#do the XML magic: %data contains result

my $q = new File::Queue (File => './importqueue', Mode => 0666);
my $json = new JSON;
my $qItem = $json->allow_nonref->encode(\%data);
$q->enq($qItem);

只要%data包含数字和 az 数据,就可以正常工作。但是当出现其中一个宽字符时(例如 ł、ą、ś、ż 等),我得到:Wide character in syswrite at /usr/lib/perl/5.10/IO/Handle.pm line 207.

我试图检查字符串是否为有效的 utf8:

print utf8::is_utf8($qItem). ':' . utf8::valid($qItem)

我确实得到了1:1- 所以是的,我确实有正确的 utf8 字符串。

我发现原因可能是 syswrite 将文件处理程序获取到不知道是 :utf8 编码文件的队列文件。

我对吗?如果是这样,有什么方法可以强制 File:Queue 使用 :utf8 文件处理程序?也许 File:Queue 不是最好的选择——我应该使用其他方法在两个 perl 脚本之间创建 FIFO 队列吗?

4

2 回答 2

3

utf8::is_utf8不会告诉您您的字符串是否使用 UTF-8 编码。(该信息甚至不可用。)

>perl -MEncode -E"say utf8::is_utf8(encode_utf8(chr(0xE9))) || 0"
0

utf8::valid不会告诉您您的字符串是否是有效的 UTF-8。

>perl -MEncode -E"say utf8::valid(qq{\xE9}) || 0"
1

两者都检查一些内部存储详细信息。你不应该需要任何一个。


File::Queue 只能传输字节串。您可以将要传输的数据序列化为字符串。

序列化文本的主要方式是字符编码,或者简称编码。UTF-8 是一种字符编码。

例如,字符串

dostępu

由以下字符组成(每个字符都是一个 Unicode 代码点):

64 6F 73 74 119 70 75

并非所有这些字符都适合字节,因此无法使用 File::Queue 发送字符串。如果您要使用 UTF-8 对该字符串进行编码,您将得到一个由以下字符组成的字符串:

64 6F 73 74 C4 99 70 75

这些字符适合字节,因此可以使用 File::Queue 发送字符串。


正如您所使用的,JSON 返回 Unicode 代码点的字符串。因此,您需要应用字符编码。

File::Queue 不提供自动为您编码字符串的选项,因此您必须自己完成。

您可以使用encode_utf8decode_utf8来自编码模块

 my $json = JSON->new->allow_nonref;
 $q->enq(encode_utf8($json->encode(\%data)));
 my $data = $json->decode(decode_utf8($q->deq()));

或者您可以让 JSON 为您进行编码/解码。

 my $json = JSON->new->utf8->allow_nonref;
 $q->enq($json->encode(\%data));
 my $data = $json->decode($q->deq());
于 2013-03-28T21:16:24.457 回答
0

看着文档......

perldoc -f syswrite
              WARNING: If the filehandle is marked ":utf8", Unicode
               characters encoded in UTF-8 are written instead of bytes, and
               the LENGTH, OFFSET, and return value of syswrite() are in
               (UTF8-encoded Unicode) characters.  The ":encoding(...)" layer
               implicitly introduces the ":utf8" layer.  Alternately, if the
               handle is not marked with an encoding but you attempt to write
               characters with code points over 255, raises an exception.  See
               "binmode", "open", and the "open" pragma, open.

man 3perl open
use open OUT => ':utf8';
...
with the "OUT" subpragma you can declare the default
       layers of output streams.  With the "IO"  subpragma you can control
       both input and output streams simultaneously.

所以我猜想添加use open OUT=> ':utf8'到你的程序顶部会有所帮助

于 2013-03-28T21:22:19.447 回答