【问题标题】:Rails 3 - How to handle PG Error incomplete multibyte characterRails 3 - 如何处理 PG 错误不完整的多字节字符
【发布时间】:2012-02-28 08:41:35
【问题描述】:

在 Rails 3.2 应用程序(Ruby 1.9.2)中,我收到以下错误

mobile_users#update 中发生 PGError:

不完整的多字节字符

这些是 Postgres 错误,但我在开发和测试模式下测试时遇到类似的 SQLIte 错误

导致此错误的参数是(故意省略了身份验证令牌)

  * Parameters: {"mobile_user"=>{"quiz_id"=>"1", "auth"=>"xxx", "name"=>"Joaqu\xEDn"}, "action"=>"update", "controller"=>"mobile_users", "id"=>"1", "format"=>"mobile"}

这是一个 JSON HTTP Put 请求,处理这个的更新操作如下

  # PUT /mobile_users/1
  # PUT /mobile_users/1.xml
  def update
    @mobile_user = current_mobile_user
    @mobile_user.attributes = params[:mobile_user]

    respond_to do |format|
      if @mobile_user.save
        format.html { redirect_to(@mobile_user, :notice => 'Mobile user was successfully updated.') }
        format.json  { head :ok }
        format.mobile  { head :ok }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.json  { render :json => @mobile_user.errors, :status => :unprocessable_entity }
        format.mobile  { render :json => @mobile_user.errors, :status => :unprocessable_entity }
        format.xml  { render :xml => @mobile_user.errors, :status => :unprocessable_entity }
      end
    end

  end

上面的参数中有问题的字符串是“Joaqu\xEDn”,这是完全有效的。 问题是我需要处理来自任何语言的所有字符集。

我假设我需要使用 iconv 库,但为了做到这一点,我需要检测要转换为 UTF8 的字符集,但我不知道如何执行此操作。

对于"name"=>"p\xEDa ",我还在 UTF-8 中得到无效的字节序列

【问题讨论】:

    标签: ruby-on-rails ruby encoding utf-8


    【解决方案1】:

    这个:

    "Joaqu\xEDn"
    

    "Joaquín" 的 ISO-8859-1 编码版本,因此它不是有效的 UTF-8,您的数据库可以投诉它。如果可能,请修复您的移动客户端以在 JSON 中使用 UTF-8;如果你不能这样做,那么你可以用这个来修复编码:

    params[:mobile_user][:name].force_encoding('iso-8859-1').encode!('utf-8')
    

    在服务器上。在服务器上修复它的问题是你必须猜测传入的编码是什么,你的猜测可能不正确。没有办法可靠地猜测特定字符串的编码,有rchardet,但它不适用于最新版本的 Ruby,而且它似乎已被放弃;您也许可以修复此 gem 以使用现代 Ruby。还有一些其他的猜测库,但它们似乎也都被废弃了。

    默认情况下,JSON 文本始终为 by definition、Unicode 和 UTF-8 编码:

    3.  Encoding
    
       JSON text SHALL be encoded in Unicode.  The default encoding is
       UTF-8.
    

    任何向您发送非 UTF-8 格式的 JSON 的客户端都是 IMO 损坏的,因为几乎所有内容都假定 JSON 将是 UTF-8。当然,在某处可能有一个编码标头指定 ISO 8859-1,或者标头可能是 UTF-8,即使它是 ISO 8859-1。

    【讨论】:

    • 关于 Unicode 与 ISO 8859-1 的评论是不正确的。 Unicode 只是说它接受完整的字符集。 ISO 8859-1 是一种支持 Unicode 字符子集(特别是 32-127)的编码。使用 ISO 8859-1 覆盖默认的 UTF-8 编码并发送简单的 ASCII 消息是完全可以的 - 但您需要在 HTTP 标头中声明编码。
    • @Andrew:是的,我明白你的意思,那不是我对英语的最佳使用。现在好点了吗?
    • 是的 - 更好,谢谢。鉴于 jamesw 在stackoverflow.com/q/9227763/1395668 遇到了 utf-8、iso-8859-1 和 unicode 的问题,原来的措辞可能会导致其他问题。干杯
    【解决方案2】:

    我在解析文件时遇到了与用户生成的数据相同的问题,并以这种方式解决了它:

    require 'iconv'
    ....
    line = Iconv.conv('UTF-8//IGNORE', 'UTF-8', line)
    #now variable line has valid utf-8 data
    

    您可以尝试覆盖 'name' setter,以便它去除非 utf8 字符:

    def name=(name)
      write_attribute(:name, Iconv.conv('UTF-8//IGNORE', 'UTF-8', name))
    end
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-10
    • 2011-10-31
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2012-11-01
    • 2011-04-24
    • 2012-04-07
    相关资源
    最近更新 更多