使用Rose :: DB :: Object在SQLite中处理UTF8编码的文本

时间:2011-02-15 04:33:48

标签: perl sqlite utf-8 cjk rose-db-object

我使用的是Rose::DB::ObjectSQLite和中文文本。我的课程看起来像这样:

package My::DB;

use base qw(Rose::DB);

__PACKAGE__->use_private_registry;

__PACKAGE__->register_db(
  driver   => 'sqlite',
  database => 'data/sqmple.db',
);

package Motorcycle;

use My::DB;

use base qw(Rose::DB::Object); 
...
sub init_db { My::DB->new() };

用于存储记录的代码:

Motorcycle->new(
  type  => $self->param('type'),
  brand => $self->param('brand'),
  color => $self->param('color'),
)->save;

用于显示数据的代码(来自Mojolicious应用程序):

<td><%= Mojo::ByteStream->new($cycle->type)->decode("utf-8") %></td>
<td><%= Mojo::ByteStream->new($cycle->brand)->decode("utf-8") %></td>
<td><%= Mojo::ByteStream->new($cycle->color)->decode("utf-8") %></td>

如何消除解码步骤?我希望显示代码看起来像这样:

<td><%= $cycle->type %></td>
<td><%= $cycle->brand %></td>
<td><%= $cycle->color %></td>

2 个答案:

答案 0 :(得分:0)

如果您将UTF8编码的文本提供给SQLite,它应该以相同的形式将其返回给您。例如,给定一个名为test.db的SQLite数据库,其中包含此模式:

CREATE TABLE things
(
  id   INTEGER PRIMARY KEY AUTOINCREMENT,
  name VARCHAR(64) NOT NULL
);

在与test.db数据库相同的目录中的脚本中运行此代码:

package My::DB;

use base qw(Rose::DB);

__PACKAGE__->use_private_registry;

__PACKAGE__->register_db
(
  driver   => 'sqlite',
  database => 'test.db',
);

package My::Thing;

use base qw(Rose::DB::Object); 

__PACKAGE__->meta->setup
(
  table   => 'things',
  columns =>
  [
    id   => { type => 'serial', primary_key => 1, not_null => 1 },
    name => { type => 'text', length => 64, not_null => 1 },
  ],
);

sub init_db { My::DB->new }

package main;

# Set the name to a UTF8-encoded smiley: Unicode 0x263A
my $thing = My::Thing->new(name => "\x{e2}\x{98}\x{ba}")->save; 

$thing = My::Thing->new(id => $thing->id)->load;

# This will print the UTF8-encoded smiley; make sure your
# terminal can handle UTF8 output.
print $thing->name, "\n";

如果这对您不起作用,那么您获取表单参数(例如$self->param('type'))的调用可能会返回字符串而不是UTF8编码的字符串。也就是说,在笑脸字符串的情况下,可能$self->param('foo')返回“\ x {263a}”而不是“\ x {x2} \ x {98​​} \ x {ba}”。在这种情况下,解决方案是在设置对象属性之前将字符串编码为UTF8:

Motorcycle->new(
  type  => utf8::encode($self->param('type')),
  brand => utf8::encode($self->param('brand')),
  color => utf8::encode($self->param('color')),
)->save;

答案 1 :(得分:0)

我认为你需要将sqlite_unicode => 1配置值降低到SQLite,有一个关于UTF-8和SQLite的similar question,设置sqlite_unicode就可以了。

我认为Rose::DB::SQLite不支持此配置参数。基于this possibly similar issue with MySQL,您可以通过将其添加到驱动程序来修补Rose :: DB :: SQLite以添加对sqlite_unicode的支持:

sub sqlite_unicode {
{
  shift->dbh_attribute_boolean('sqlite_unicode', @_)
}

我会对约翰的答案发表评论,这样他就可以理智地检查一下。

如果可以,那么您可能想要向John Siracusa发送补丁(他不仅已经在这个问题上,而且还有Rose :: DB维护者)。