我正在使用CGI :: Session将utf-8会话数据存储到MySQL数据库中,YAML作为序列化程序,工作正常。问题是,在解冻时,会话数据似乎没有被解码为Perls内部格式,尽管传递给会话构造函数的数据库句柄被配置为这样做。 解冻后立即在每个会话参数上手动应用decode_utf8可以解决这个问题,但这样做很不方便。
这是我的设置:
use warnings;
use strict;
$dbh->{'mysql_enable_utf8'} = 1;
$dbh->do('set names utf8');
$session = CGI::Session->new("driver:MySQL;serializer:yaml", undef, {
TableName => "session",
IdColName => "id",
DataColName => "data",
Handle => $dbh,
} ) or die CGI::Session->errstr;
# column 'data' of table 'session' is of type mediumtext, has charset utf8 and collation utf8_unicode_ci
示例摘录:
binmode(STDIN, ":encoding(utf8)");
binmode(STDOUT, ":encoding(utf8)");
if( !defined $session->param('first_name') ){
$session->param('first_name','jörg');
}
print $session->param('first_name');
首次运行时会输出:'jörg'
第二次运行(名称现在来自会话表):'jörg'
如上所述,这将解决它:
binmode(STDIN, ":encoding(utf8)");
binmode(STDOUT, ":encoding(utf8)");
if( !defined $session->param('first_name') ){
$session->param('first_name','jörg');
} else {
$session->param('first_name',decode_utf8($session->param('first_name')));
}
print $session->param('first_name');
(我使用完全相同的数据库句柄在'person'表中存储'first_name',并且从那里可以完美地读取/写入/输出。)
那么,为什么数据不能通过CGI :: Session正确解码成Perls格式,或者如何告诉CGI :: Session呢? 此行为还会导致序列化程序Dumper,Storable和FreezeThaw在尝试解冻之前已损坏的数据时崩溃。 例如。当转储器不是Perls内部格式时,Dumper会在'jörg'的'ö'中删除会话数据。
非常感谢您对此提出的任何暗示,请原谅我的不足之处。我只想试着解决unicode-in-perl问题。 (是的,我已经阅读了许多一般指南和操作方法,但遗憾的是在session-mysql主题上找不到任何内容。)
祝你好运, 托马斯
根据simbaque更新(感谢提示),但这确实不是问题。
答案 0 :(得分:0)
在您的示例中,我看到您将输出设置为UTF8,但是您是否将输入设置为UTF8? toString()
has a warning关于UTF8,在该部分中讨论了如何将输入和输出设置为UTF8。如果您添加toString()
?
答案 1 :(得分:0)
听起来表格列未被声明为CHARACTER SET utf8
。
答案 2 :(得分:0)
没有准确回答原始问题,但这两个选项对于遇到类似问题的其他人来说可能是有效的解决方法:
使用默认的串行器Data :: Dumper并强制它使用纯perl版本似乎能够在设置utf8标志的情况下根据需要恢复数据。缺点是,它应该比默认使用的perl / XS版本慢得多。
$Data::Dumper::Useperl = 1;
使用可存储的序列化程序并将数据列更改为mediumblob
类型。这可能会完全绕过整个编码问题,因为您只是从DB读取和写入二进制数据。但数据列不再是人类可读的。