我正在处理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
包含数字和a-z数据,这只能正常工作。但当其中一个广告出现时(例如,ł,±,ś,ż等)我得到: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不是最好的选择 - 我应该使用sth else在两个perl脚本之间创建FIFO队列吗?
答案 0 :(得分: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_utf8
和decode_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());
答案 1 :(得分: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'
会有所帮助