【问题标题】:Handling UTF8-encoded text in SQLite using Rose::DB::Object使用 Rose::DB::Object 在 SQLite 中处理 UTF8 编码的文本
【发布时间】:2011-06-27 08:38:03
【问题描述】:

我用的是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>

【问题讨论】:

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


    【解决方案1】:

    我认为您需要将 sqlite_unicode =&gt; 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 维护者)发送补丁。

    【讨论】:

      【解决方案2】:

      如果您将 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-&gt;param('type'))的调用可能会返回字符串而不是 UTF8 编码的字符串。也就是说,在笑脸字符串的情况下,$self-&gt;param('foo') 可能返回“\x{263a}”而不是“\x{e2}\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;
      

      【讨论】:

      • 我不需要设置 sqlite_unicode 属性来使我的示例工作。也就是说,为它添加一个方法到 Rose::DB 可能是值得的。我将添加到我的 TODO 中。
      • 包 MY::DB;使用基础 qw(Rose::DB); ->use_private_registry; PACKAGE->default_connect_options( sqlite_unicode => 1 );在网上搜索,找到细线,它在这个简单的例子中有效。这种方法应该安全吗?
      猜你喜欢
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 2019-07-18
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多