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'
何がうまくいかないのですか?
私"\xBF"
はそれがUTF-8でエンコードされているとすでに考えているencode
と思います.
>> s = "\xBF"
=> "\xBF"
>> s.encoding
=> #<Encoding:UTF-8>
\xBF
は有効な UTF-8 ではないため、これはもちろんナンセンスです。しかし、 の 3 つの引数形式を使用すると、次のようになりますencode
。
encode(dst_encoding, src_encoding [, options] ) → str
[...] 2 番目の形式は、
str
トランスコードされた fromsrc_encoding
toのコピーを返しますdst_encoding
。
encode
文字列がそのエンコーディングであると考えているものを無視し、それをバイナリデータとして扱うように指示することで、問題を強制できます。
>> foo = s.encode('utf-8', 'binary', :invalid => :replace, :undef => :replace)
=> "�"
上からUTF-8だと思うs
のはどこだ。"\xBF"
force_encoding
on を使用しs
て強制的にバイナリにしてから、2 つの引数を使用することもできます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)
=> "�"
使用できるASCII文字のみを使用している場合
>> "Hello \xBF World!".encode('utf-8', 'binary', :invalid => :replace, :undef => :replace)
=> "Hello � World!"
しかし、ascii では無効な有効な UTF8 文字で同じアプローチを使用するとどうなるでしょうか。
>> "¡Hace \xBF mucho frío!".encode('utf-8', 'binary', :invalid => :replace, :undef => :replace)
=> "��Hace � mucho fr��o!"
ええとああ!frío をアクセントのままにしておきます。有効な UTF8 文字を保持するオプションを次に示します。
>> "¡Hace \xBF mucho frío!".chars.select{|i| i.valid_encoding?}.join
=> "¡Hace mucho frío!"
また、Ruby 2.1 には、scrub
この問題を解決するという新しいメソッドがあります。
>> "¡Hace \xBF mucho frío!".scrub
=> "¡Hace � mucho frío!"
>> "¡Hace \xBF mucho frío!".scrub('')
=> "¡Hace mucho frío!"
これは、明示的なコード ページを使用してソース テキスト ファイルを読み取ると修正されます。
File.open( 'thefile.txt', 'r:iso8859-1' )