在IRB,我正在尝试以下方面:
1.9.3p194 :001 > foo = "\xBF".encode("utf-8", :invalid => :replace, :undef => :replace)
=> "\xBF"
1.9.3p194 :002 > foo.match /foo/
ArgumentError: invalid byte sequence in UTF-8
from (irb):2:in `match'
Run Code Online (Sandbox Code Playgroud)
有什么想法会出错吗?
mu *_*ort 22
我猜它"\xBF"已经认为它是用UTF-8编码的,所以当你打电话时encode,它认为你正在尝试用UTF-8编码UTF-8字符串而什么都不做:
>> s = "\xBF"
=> "\xBF"
>> s.encoding
=> #<Encoding:UTF-8>
Run Code Online (Sandbox Code Playgroud)
\xBF是无效的UTF-8,所以这当然是胡说八道.但是如果你使用以下三种形式encode:
encode(dst_encoding,src_encoding [,options])→str
[...]第二种形式返回的副本
str从转码src_encoding到dst_encoding.
您可以通过告知encode忽略字符串认为其编码是什么来强制解决问题,并将其视为二进制数据:
>> foo = s.encode('utf-8', 'binary', :invalid => :replace, :undef => :replace)
=> "?"
Run Code Online (Sandbox Code Playgroud)
哪里s是"\xBF"说认为它是UTF-8从上面.
您也可以使用force_encodingon s强制它为二进制,然后使用两个参数encode:
>> s.encoding
=> #<Encoding:UTF-8>
>> s.force_encoding('binary')
=> "\xBF"
>> s.encoding
=> #<Encoding:ASCII-8BIT>
>> foo = s.encode('utf-8', :invalid => :replace, :undef => :replace)
=> "?"
Run Code Online (Sandbox Code Playgroud)
如果您只使用 ascii 字符,则可以使用
>> "Hello \xBF World!".encode('utf-8', 'binary', :invalid => :replace, :undef => :replace)
=> "Hello ? World!"
Run Code Online (Sandbox Code Playgroud)
但是如果我们对 ascii 中无效的有效 UTF8 字符使用相同的方法会发生什么
>> "¡Hace \xBF mucho frío!".encode('utf-8', 'binary', :invalid => :replace, :undef => :replace)
=> "??Hace ? mucho fr??o!"
Run Code Online (Sandbox Code Playgroud)
哦哦!我们希望 frío 保持口音。这是一个保留有效 UTF8 字符的选项
>> "¡Hace \xBF mucho frío!".chars.select{|i| i.valid_encoding?}.join
=> "¡Hace mucho frío!"
Run Code Online (Sandbox Code Playgroud)
同样在 Ruby 2.1 中有一个新方法叫做scrub解决这个问题
>> "¡Hace \xBF mucho frío!".scrub
=> "¡Hace ? mucho frío!"
>> "¡Hace \xBF mucho frío!".scrub('')
=> "¡Hace mucho frío!"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9424 次 |
| 最近记录: |