2013-03-28 40 views
0

我正在處理來自perl中XML文件的一些數據,並希望使用FIFO File :: Queue來劃分和加速這個過程。 一個Perl腳本解析XML文件,並準備JSON輸出另一個腳本:如何讓File :: Queue能夠在perl中處理utf8字符串?

#!/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的數據只有這個工作正常。但是,當widechars之一發生(例如,L,A,S,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得到的FileHandler到不知道是一個隊列文件:UTF8編碼文件。

我對不對?如果是的話有什麼辦法強制File:Queue使用:utf8文件處理程序? 也許文件:隊列不是最好的選擇 - 我應該使用sth else在兩個Perl腳本之間創建FIFO隊列嗎?

回答

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 

這些字符適合字節,這樣字符串可以使用文件::隊列發送。


正如您使用的那樣,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()); 
+0

感謝很多的clariffication。 JSON內部utf8編碼'JSON-> new-> utf8-> allow_nonref;'創造了我的日子;-) – TomekK

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'你的程序的頂部將有助於

+0

'使用open'的效果在詞彙範圍內。除非將它添加到File/Queue.pm本身,否則它將無濟於事,那將是錯誤的。 – ikegami

+0

@ikegami怎麼樣''binmode $ q - > {queue}':utf8'''然後呢? :) – Vorsprung

+0

這可能會正常工作,但我必須檢查模塊以確保。這絕對不是最安全的方法。 – ikegami