【问题标题】:Why is Encode::decode('UTF-8', $var) still needed when everything is already in UTF-8?当一切都已经在 UTF-8 中时,为什么仍然需要 Encode::decode('UTF-8', $var) ?
【发布时间】:2011-09-23 01:37:15
【问题描述】:

在我维护的 Web 应用中,我尝试将所有内容都保存为 UTF-8:

  • 数据库 (CHARSET=utf8)
  • 源文件(使用 utf8;用 utf8 编写)
  • 模板(对于 Template Toolkit,使用 ENCODING => utf8)
  • 用户输入和输出(HTTP 中的 charset=utf8 标头,binmode :utf8 用于 STDIN 和 STDOUT)

但对于来自数据库的数据,我仍然需要使用 Encode::decode('UTF-8',$data),否则它们会被双重编码或以某种方式损坏。

这是为什么?我怎样才能摆脱这个烦人的额外步骤?难道不应该有办法只保留所有内容,每次都以 UTF-8 格式保存,而无需手动转换任何内容吗?

【问题讨论】:

    标签: mysql perl utf-8 cgi encode


    【解决方案1】:

    在内部,您的数据库可能会将所有数据保存为固定的原始格式,通常是 UCS-4(即每个包含一个代码点的 32 位整数的原始字符串)。 UTF8 是一种编码,编码仅在序列化数据时使用(例如在文件或数据库中)。反序列化,即读取,意味着解码编码数据并检索原始代码点字符串。

    仅仅因为您碰巧对所有序列化需求使用了相同的编码,并不妨碍您在加载时解码和写入时编码。

    【讨论】:

    • 在 mySQL 数据库中不正确:声明为 UTF-8 的数据存储为 UTF-8。
    • 此外,如果访问 api 处理重新编码字符以符合客户的期望,则存储可能无关紧要;它甚至可能是客户端/服务器网络协议的一部分。
    • 对于任何框架来说,在特定的多字节编码中维护一个内部字符串缓冲区都是非常麻烦的......你将如何进行字符串长度计算?您甚至无法确定您读取的数据是否有效。也许有些程序可以,但其他程序可能不会。
    • “对于任何框架来说,在特定的多字节编码中维护一个内部字符串缓冲区都是非常麻烦的”——Ruby 1.9 正是这样做的:每个字符串都有自己的编码属性,并且调用它的长度方法来处理相应地使用它。
    【解决方案2】:
    【解决方案3】:

    要从数据库中正确获取 utf-8,您需要在连接时明确告诉它:

    my $dbh = DBI->connect( "dbi:mysql:dbname=$db;host=localhost",
           "user", "pwd", {mysql_enable_utf8 => 1 })
    

    正如我在问题here 中所问的那样,它仍然存在一些问题,但在大多数情况下它工作正常。

    要回答“为什么”部分要困难得多。正如丹尼斯指出的那样,最近关于“为什么”的话题非常多。也许它可以帮助您理解相关的事情。我建议使用 utf8::all` 模块来让 utf-8 处理更容易和更干净。

    【讨论】:

      猜你喜欢
      • 2020-06-03
      • 1970-01-01
      • 1970-01-01
      • 2017-07-20
      • 2016-02-24
      • 2012-06-28
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多