jos*_*hm1 11 ruby unicode utf-8 ruby-1.9
我知道关于这个错误有很多类似的问题,我已经尝试了很多没有运气的问题.我遇到的问题涉及字节\xA1并且正在抛出
ArgumentError:UTF-8中的无效字节序列
我试过以下但没有成功:
"\xA1".encode('UTF-8', :undef => :replace, :invalid => :replace,
:replace => "").sub('', '')
"\xA1".encode('UTF-8', :undef => :replace, :invalid => :replace,
:replace => "").force_encoding('UTF-8').sub('', '')
"\xA1".encode('UTF-8', :undef => :replace, :invalid => :replace,
:replace => "").encode('UTF-8').sub('', '')
Run Code Online (Sandbox Code Playgroud)
每一行都为我抛出错误.我究竟做错了什么?
更新:
上述行仅在IRB中失败.但是,我修改了我的应用程序,使用相同的String#encode方法和参数对CVS文件的行进行编码,从文件中读取行时出现相同的错误(注意:如果对同一个字符串执行操作,它会起作用没有使用IO).
bad_line = "col1\tcol2\tbad\xa1"
bad_line.sub('', '') # does NOT fail
puts bad_line # => col1 col2 bad?
tmp = Tempfile.new 'foo' # write the line to a file to emulate real problem
tmp.puts bad_line
tmp.close
tmp2 = Tempfile.new 'bar'
begin
IO.foreach tmp.path do |line|
line.encode!('UTF-8', :undef => :replace, :invalid => :replace, :replace => "")
line.sub('', '') # fail: invalid byte sequence in UTF-8
tmp2.puts line
end
tmp2.close
# this would fail if the above error didn't halt execution
CSV.foreach(tmp2.path) do |row|
puts row.inspect # fail: invalid byte sequence in UTF-8
end
ensure
tmp.unlink
tmp2.close
tmp2.unlink
end
Run Code Online (Sandbox Code Playgroud)
Fre*_*ung 31
似乎ruby认为字符串编码已经是utf8,所以当你这样做时
line.encode!('UTF-8', :undef => :replace, :invalid => :replace, :replace => "")
Run Code Online (Sandbox Code Playgroud)
它实际上没有做任何事情,因为目标编码与当前编码相同(至少这是我对代码的解释transcode.c)
这里真正的问题是你的起始数据是否在某些不是utf-8的编码中是有效的,或者这是否是应该是utf-8的数据,但是它有一些你要丢弃的瑕疵.
在第一种情况下,正确的做法是告诉ruby这种编码是什么.您可以在打开文件时执行此操作
File.open('somefile', 'r:iso-8859-1')
Run Code Online (Sandbox Code Playgroud)
将打开文件,将其内容解释为iso-8859-1
你甚至可以让ruby为你转码
File.open('somefile', 'r:iso-8859-1:utf-8')
Run Code Online (Sandbox Code Playgroud)
将以iso-8859-1打开文件,但是当您从中读取数据时,字节将被转换为utf-8.
你也可以调用force_encoding告诉ruby字符串的编码是什么(这根本不会修改字节,它只是告诉ruby如何解释它们).
在第二种情况下,你只想转储你的utf-8中的任何讨厌的东西,你不能只是打电话encode!,因为这是一个无操作.在ruby 2.1及更高版本中,您可以使用String#scrub,在以前的版本中,您可以执行此操作
line.encode!('UTF-16', :undef => :replace, :invalid => :replace, :replace => "")
line.encode!('UTF-8')
Run Code Online (Sandbox Code Playgroud)
我们首先转换为utf-16.由于这是一种不同的编码,因此ruby实际上会替换我们的无效序列.然后我们可以转换回utf-8.这不会丢失任何额外的数据,因为utf-8和utf-16只是编码相同底层字符集的两种不同方式.
| 归档时间: |
|
| 查看次数: |
11457 次 |
| 最近记录: |