【问题标题】:British Pound Sign £ causing PG::CharacterNotInRepertoire: ERROR: invalid byte sequence for encoding “UTF8”: 0xa3英镑符号 £ 导致 PG::CharacterNotInRepertoire:错误:用于编码“UTF8”的无效字节序列:0xa3
【发布时间】:2016-05-13 09:10:49
【问题描述】:

当通过 csv 文件从外部来源(例如我的银行)收集包含英镑符号“£”的信息并使用 ActiveRecord 发布到 postgres 时,我收到错误:

PG::CharacterNotInRepertoire: ERROR: invalid byte sequence for encoding “UTF8”: 0xa3

0xa3 是 £ 符号的十六进制代码。感知的智慧是在字符串上明确指定 UTF-8,同时替换无效的字节序列..

string.encode('UTF-8', {:invalid => :replace, :undef => :replace, :replace => '?'})

这会阻止错误,但这是一个有损修复,因为“£”被转换为“?”

UTF-8 能够处理“£”符号,那么如何修复无效的字节序列并保留“£”符号?

【问题讨论】:

  • 0xa3 是 microsuft 的 cp1252(和 iso8859-1)中井号的代码点。您的数据可能未编码为 utf8。 en.wikipedia.org/wiki/Windows-1252
  • 你是对的@wildplasser,源文件有微软编码——一个带有.xls扩展名的HTML文件下载。 Ruby 将其作为 UTF-8 处理,除了 £ 符号之前没有正确的字符序列。

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


【解决方案1】:

感谢 Michael Fuhr 回答我自己的问题,他解释了 UTF-8 byte sequence 的磅符号是 0xc2 0xa3。所以,你所要做的就是找到每个出现的 0xa3 (163) 并将 0xc2 (194) 放在它前面...

array_bytes = string.bytes
new_pound_ptr = 0
# Look for £ sign 
pound_ptr = array_bytes.index(163)
while !pound_ptr.nil?
  pound_ptr+= new_pound_ptr # new_pound_ptr is set at end of block
  # The following statement finds incorrectly sequenced £ sign...
  if (pound_ptr == 0) || (array_bytes[pound_ptr-1] != 194)
    array_bytes.insert(pound_ptr,194)
      pound_ptr+= 1
    end
    new_pound_ptr = pound_ptr
    # Search remainder of array for pound sign
    pound_ptr = array_bytes[(new_pound_ptr+1)..-1].index(163)
  end
end
# Convert bytes to 8-bit unsigned char, and UTF-8
string = array_bytes.pack('C*').force_encoding('UTF-8') unless new_pound_ptr == 0
# Can now write string to model without out-of-sequence error..
hash["description"] = string
Model.create!(hash)

我在这个 stackoverflow 论坛上得到了很多帮助,希望我能帮助到其他人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 2022-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多