如何让File::Queue能够在perl中处理utf8字符串?

如何让File::Queue能够在perl中处理utf8字符串?,perl,encoding,utf-8,fifo,widechar,Perl,Encoding,Utf 8,Fifo,Widechar,我正在用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

我正在用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数据,就可以正常工作。但当其中一个widechar出现时(如ł、ą、ś、ż等),我得到:
syswrite中的宽字符位于/usr/lib/perl/5.10/IO/Handle.pm第207行。

我已尝试检查字符串是否有效utf8:

print utf8::is_utf8($qItem). ':' . utf8::valid($qItem)
我得到了
1:1
-所以是的,我有正确的utf8字符串

我发现原因可能是syswrite将filehandler获取到队列文件,而队列文件不知道是:utf8编码的文件

我说得对吗?如果是这样,有没有办法强制File:Queue使用:utf8文件处理程序?
也许File:Queue不是最佳选择-我应该使用其他方法在两个perl脚本之间创建FIFO队列吗?

utf8::is\u utf8
不会告诉您字符串是否使用UTF-8编码。(这些信息甚至不可用。)

utf8::valid
不会告诉您字符串是否有效

>perl -MEncode -E"say utf8::valid(qq{\xE9}) || 0"
1
两者都检查一些内部存储详细信息。你不应该有任何需要


文件::队列只能传输字节字符串。由您将要传输的数据序列化为字符串

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

例如,字符串

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

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

64 6F 73 74 C4 99 70 75
这些字符以字节为单位,所以可以使用File::Queue发送字符串


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

文件::队列没有为您提供自动编码字符串的选项,所以您必须自己进行编码

您可以使用编码模块中的
encode\u utf8
decode\u 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());

utf8::is\u utf8
不会告诉您字符串是否使用UTF-8编码。(这些信息甚至不可用。)

utf8::valid
不会告诉您字符串是否有效

>perl -MEncode -E"say utf8::valid(qq{\xE9}) || 0"
1
两者都检查一些内部存储详细信息。你不应该有任何需要


文件::队列只能传输字节字符串。由您将要传输的数据序列化为字符串

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

例如,字符串

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

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

64 6F 73 74 C4 99 70 75
这些字符以字节为单位,所以可以使用File::Queue发送字符串


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

文件::队列没有为您提供自动编码字符串的选项,所以您必须自己进行编码

您可以使用编码模块中的
encode\u utf8
decode\u 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());

看看这些文件

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.

因此,我想在程序顶部添加
使用openout=>':utf8'
将有助于查看文档

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.

因此,我想在程序的顶部添加
使用open=>':utf8'
将有助于
使用open
的效果是词汇范围的。除非您将其添加到文件/Queue.pm本身,否则它不会有帮助,这是错误的。@ikegami
binmode$q->{Queue}:utf8'
then?:)怎么样这可能行得通,但我必须复习一下模块才能确定。这绝对不是最安全的方法。
使用open
的效果是词汇范围的。除非您将其添加到文件/Queue.pm本身,否则它不会有帮助,这是错误的。@ikegami
binmode$q->{Queue}:utf8'
then?:)怎么样这可能行得通,但我必须复习一下模块才能确定。这绝对不是最安全的方法。非常感谢你的澄清。JSON内部utf8编码
JSON->new->utf8->allow\u nonref成就我的一天;-)非常感谢你的澄清。JSON内部utf8编码
JSON->new->utf8->allow\u nonref成就我的一天;-)