例
文字列がすべてひらがなで構成されているかを調べるメソッドを定義しました。
def all_hiragana?(str) = str.match?(/\A\p{Hiragana}+\z/)
all_hiragana?('もぐたろう')
#=> true
all_hiragana?('もぐタロー')
#=> false
# \x というバックスラッシュ記法で 16 進数の表現に変換しても、結果は同じ。
'もぐたろう'.b
#=> "\xE3\x82\x82\xE3\x81\x90\xE3\x81\x9F\xE3\x82\x8D\xE3\x81\x86"
all_hiragana?("\xE3\x82\x82\xE3\x81\x90\xE3\x81\x9F\xE3\x82\x8D\xE3\x81\x86")
#=> true
このメソッドにある文字列を渡すと invalid byte sequence in UTF-8 (ArgumentError)
というエラーが発生します。
find_invalid_bytes("\xE3\x82\x82\x82\xAE\xE3\x81\x9F\x82\xEB\xE3\x81\x86")
# invalid byte sequence in UTF-8 (ArgumentError)
これは UTF-8 として不正なバイト列が含まれていることを示しています。しかし、具体的にどのバイト列が不正なのかはエラーメッセージからは分かりません。それを調べたいです。
方法
String#scrub という不正なバイト列を置き換えるためのメソッドを使用します。
def find_invalid_bytes(str)
invalid_bytes = []
str.scrub do |bytes|
invalid_bytes << bytes
# ブロックを渡す場合、
# 不正なバイト列を置き換える文字列を戻り値で必ず指定する必要がある。
'?'
end
invalid_bytes
end
先ほどエラーになった文字列をこの find_invalid_bytes
に渡すと、不正なバイト列を返します。
find_invalid_bytes("\xE3\x82\x82\x82\xAE\xE3\x81\x9F\x82\xEB\xE3\x81\x86")
#=> ["\x82", "\xAE", "\x82", "\xEB"]
これは実は Shift_JIS で「ぐ」と「ろ」を表すバイト列でした。
invalid_str = ["\x82", "\xAE", "\x82", "\xEB"].join
invalid_str.force_encoding(Encoding::Shift_JIS).encode(Encoding::UTF_8)
#=> "ぐろ"
'ぐ'.encode(Encoding::Shift_JIS)
#=> "\x{82AE}"
'ろ'.encode(Encoding::Shift_JIS)
#=> "\x{82EB}"
バージョン情報
$ ruby -v
ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [arm64-darwin24]
参考
Ruby リファレンス
過去に書いた Ruby と文字コードに関する記事