2010-03-27 77 views
1

我遇到了一个非常奇怪的UTF-8问题Net::Cassandra::Easy(它建立在Net::Cassandra上):写入Cassandra的UTF-8字符串在检索时出现乱码。Perl的Net :: Cassandra模块是否支持UTF-8?

下面的代码显示该问题:

use strict; 
use utf8; 
use warnings; 
use Net::Cassandra::Easy; 

binmode(STDOUT, ":utf8"); 

my $key = "some_key"; 
my $column = "some_column"; 
my $set_value = "\x{2603}"; # U+2603 is ☃ (SNOWMAN) 
my $cassandra = Net::Cassandra::Easy->new(keyspace => "Keyspace1", server => "localhost"); 
$cassandra->connect(); 
$cassandra->mutate([$key], family => "Standard1", insertions => { $column => $set_value }); 
my $result = $cassandra->get([$key], family => "Standard1", standard => 1); 
my $get_value = $result->{$key}->{"Standard1"}->{$column}; 
if ($set_value eq $get_value) { 
    # this is the path I want. 
    print "OK: $set_value == $get_value\n"; 
} else { 
    # this is the path I get. 
    print "ERR: $set_value != $get_value\n"; 
} 

当运行上述$set_value eq $get_value代码的计算结果为false。我究竟做错了什么?

+0

阅读后可能需要Encode :: decode_utf8。 (实际上,Encode :: encode_utf8用于写入。) – jrockway 2010-03-27 00:48:42

回答

4

use Encode;添加到脚本的开头,并通过Encode::decode_utf8传递变量。例如:

my $get_value = $result->{$key}->{"Standard1"}->{$column}; 
$get_value = Encode::decode_utf8($get_value); 

输出:

OK: ☃ == ☃ 

当设置$set_value到 “\ X {2603}”,Perl中检测到宽字符,并将字符串编码为UTF-8为您服务。要确认这一点,请打印返回值Encode::is_utf8($set_value)

不幸的是,一旦这个字符串进入Cassandra并再次退出,编码信息就会丢失。看来卡桑德拉是编码不可知的。调用Encode::decode_utf8告诉Perl您有一个包含UTF-8字节序列的字符串,并且它应该转换为用于Unicode的Perl内部表示。正如jrockway所指出的那样,在任何字符串发送给Cassandra之前,您还应该调用Encode::encode_utf8,尽管在大多数情况下,Perl已经知道它们是UTF-8,例如,如果您使用:utf8编码层打开了一个文件。

如果你经常使用UTF-8,你可能想要通过Net :: Cassandra :: Easy编写一个包装来自动完成。

最后,你不需要use utf8;除非你的Perl 源代码(可变,评论等)包含UTF-8字符。无论您是否指定use utf8;,Perl都可以处理UTF-8 字符串

+0

感谢您的回答,但是由于“☃”而不是“â”,恐怕不能解决问题。我期望的输出是“OK:☃==☃”而不是“OK:â==â”。 – knorv 2010-03-27 10:53:13

+0

糟糕,使用PuTTY并忘记设置UTF-8字符集。我会尽快给您回复。 – rjh 2010-03-27 11:10:26

+0

使用UTF-8时,上面的代码显示“OK:☃==☃”。答案已更新。 – rjh 2010-03-27 11:12:06