ArgumentError: invalid byte sequence in UTF-8
- Backend
- 09 Dec, 2018
有次遇到這個錯誤:ArgumentError: invalid byte sequence in UTF-8,一追之下發現是遇到類似這段程式碼,
"english 中文\xED\xB6\xB0".gsub(/english/, '')
會錯的原因是因為 \xED\xB6\xB0 不是合法的 UTF-8 編碼。
要檢查是不是合法的編碼可以用 valid_encoding? ,
> "\xED".encoding
=> #<Encoding:UTF-8>
> "\xED".valid_encoding?
=> false
所以這坨東西要怎麼變回去呢?可以用 pack 和 unpack ,
> "\xED".unpack('C*')
=> [237]
> "\xED".unpack('C*').pack('U*')
=> "í"
這段程式的意思大意是先將 "\xED" 轉成 unsigned char integer array,再組回 UTF**-**8 String。可以再檢查一下轉完的是什麼東西,
> "í".unpack('C*')
=> [195, 173]
可以發現 \xED 已經變成不同的東西了。
查詢一下可以發現, í 在 UTF-8 的 Unicode code point 是表示成 U+00ED。
如果要將不合法的字元直接處理掉,可以用 scrub ,
> "english 中文\xED\xB6\xB0".scrub('?')
=> "english 中文???"
如果要將不合法的字元用上面的方法換成可能正確的字元,可以在 scrub 塞 block,
> "english 中文\xED\xB6\xB0".scrub{|char| char.unpack('C*').pack('U*')}
=> "english 中文í¶°"