@kyanny's blog

My life. Opinions are my own.

マルチバイト文字

#!/usr/bin/env ruby
# coding: utf-8

# Shift_JIS (CP932)
"".encode('cp932').ord # => 33440
"".encode('cp932').ord.to_s(16) # => "82a0"
"".encode('cp932').codepoints.first.to_s(16) # => "82a0"
a = "".encode('cp932').ord.to_s(2) # => "1000001010100000"

"".encode('cp932').bytes # => [130, 160]
"".encode('cp932').bytes.map{ |b| b.to_s(16) } # => ["82", "a0"]
"".encode('cp932').bytes.map{ |b| b.to_s(2) } # => ["10000010", "10100000"]
b = "".encode('cp932').bytes.map{ |b| b.to_s(2) }.join # => "1000001010100000"

a # => "1000001010100000"
b # => "1000001010100000"
a == b # => true

# UTF-8
# String#ord は Unicode コードポイントを返す
"".ord # => 12354
"".ord.to_s(16) # => "3042"
"".codepoints.first.to_s(16) # => "3042"
a = "".ord.to_s(2) # => "11000001000010"

"".bytes # => [227, 129, 130]
"".bytes.map{ |b| b.to_s(16) } # => ["e3", "81", "82"]
"".bytes.map{ |b| b.to_s(2) } # => ["11100011", "10000001", "10000010"]
b = "".bytes.map{ |b| b.to_s(2) }.join # => "111000111000000110000010"

a # => "11000001000010"
b # => "111000111000000110000010"
a == b # => false
  • ShiftJIS の「あ」の1バイト目は 82 2バイト目は a0
  • String#ord が返す「あ」のコードポイントは16進数で 82a0
  • 82 a0 という2バイトが並んでいるデータ == 82a0 で2バイトなデータ
  • UTF-8 の「あ」の1バイト目は e3 2バイト目は 81 3バイト目は 82
  • String#ord が返す「あ」のコードポイントは16進数で 3042 これはユニコード番号(Unicode コードポイント)であり各バイトの値とは無関係
  • 結論: String#bytes または xxd コマンドで各バイトの値をちゃんとみる