如何使用Perl的DBI处理unicode?

时间:2009-06-11 21:22:09

标签: perl unicode dbi

我的delicious-to-wp perl script可以正常工作,但是除了更奇怪的输出外,还会给所有“怪异”字符。 所以我试过

$description = decode_utf8( $description ); 

但这并没有什么区别。我想要,例如“活着”变成“上线”而不是“活着”我如何处理Perl中的unicode以便这样做?

更新:我发现问题是设置我必须在Perl中设置的DBI:

my $sql = qq{SET NAMES 'utf8';};
$dbh->do($sql);

那是我必须设置的部分,很棘手。谢谢!

6 个答案:

答案 0 :(得分:19)

值得注意的是,如果您运行的DBD :: mysql版本足够新(3.0008开启),您可以执行以下操作:$dbh->{'mysql_enable_utf8'} = 1;然后编辑所有内容的decode()ed / encode()你在离开/进入DBI的路上。

答案 1 :(得分:13)

当您连接到数据库时启用UTF8:

my $dbh = DBI->connect(
    "dbi:mysql:dbname=db_name", 
    "db_user", "db_pass",
     {RaiseError => 0, PrintError => 0, mysql_enable_utf8 => 1}
 ) or die "Connect to database failed.";

这样可以获得字符模式字符串,并根据需要设置UTF8标志。

来自DBI General Interface Rules & Caveats

  

Perl支持两种字符串:Unicode(内部为utf8)和非Unicode(如果强制采用编码,则默认为iso-8859-1)。驱动程序应接受这两种字符串,如果需要,将它们转换为正在使用的数据库的字符集。同样,当从数据库中获取非iso-8859-1的字符数据时,驱动程序应将其转换为utf8。

来自DBD::mysql的mysql_enable_utf8

的细节
  

此外,打开此标志会告诉MySQL应将传入数据视为UTF-8。这只有在用作connect()调用的一部分时才会生效。如果在连接后打开标志,则需要发出命令SET NAMES utf8以获得相同的效果。

答案 2 :(得分:4)

术语

$dbh->do(qq{SET NAMES 'utf8';});

绝对可以节省访问utf-8声明数据库的日期,但需要注意的是,如果您要对从数据库中删除的任何数据进行任何perl处理,那么存储它是明智的在perl var中作为utf8字符串,因为此操作不是隐式的。

$utfstring = decode('utf8',$string_from_db);

当然,为了正确处理utf8字符串(读取,打印,写入输出),请记住设置

use open ':utf8';

binmode STDOUT, ":utf8";

后者对于打印utf8字符串至关重要。希望这会有所帮助。

答案 3 :(得分:3)

它可能与Perl无关。检查以确保在相关的MySQL表列中使用UTF编码。

答案 4 :(得分:1)

离开这个öne:

binmode STDOUT, ":utf8";

使用时:

$dbh->do(qq{SET NAMES 'utf8';});

否则您的输出将具有双utf8编码,导致双字节字符不可读! 我花了几个小时才想出来......

答案 5 :(得分:0)

默认情况下,驱动程序Perl / MySQL处理二进制数据(至少我从MySQL 5.1和5.5的一些实验中得出结论)。

在没有设置mysql_enable_utf8的情况下,我在写入/读取数据库之前将字符串编码/解码为UTF-8。

不应该将perl-internal字符串表示作为字节数组;请注意,内部'utf8'不能保证是标准的UTF-8;相反,单字节编码不保证是ISO-8859-1;真的对UTF-8进行编码/解码(而不是'utf8')。

还有一些MySQL的设置(比如上面的SET NAMES,据我记得有一个客户端编码,一个连接编码和一个服务器编码,如果它们不是全部都有,那么我的交互不太清楚关于编码的相同价值;将所有这些设置为UTF-8,上面的配方对我有用。