文字コードって何?UnicodeやUTF-8とは違うの?
文字コードについて理解しよう
エンジニアになると文字コードという言葉を聞く機会は多いと思います。
しかし、実は文字コードについて説明できるエンジニアは少ないのではないでしょうか。
私は普段Laravelを使用しており、Laravelでcsv出力する場合文字化けが発生するケースがあります。
そのバグの原因ついて深く理解するためには文字コードやBOMについて理解する必要があるため記事にしました。
文字化けのバグの原因も説明していますので是非読んでみてください。
この記事では以下の3つについて解説をしていきたいと思います。
- 文字コードとは
- なぜ文字化けが起きるのか
- BOMとは
それではよろしくお願いいたします!
文字コードとは
文字コードと聞くと「Shift_JIS」や「UTF-8」、「Unicode」という言葉を思い浮かべると思います。
ただ、本当に上記で思い浮かべた言葉は文字コードなのでしょうか。
そのあたりをPCが文字を認識する仕組みから理解し、それぞれの言葉を明確にしていきたいと思います。
wikipediaで文字コードの説明は以下のように書かれています。
文字コード(もじコード)は、コンピュータ上で文字(キャラクタ)を利用する目的で各文字に割り当てられるバイト表現。もしくは、バイト表現と文字の対応関係(文字コード体系)のことを指して「文字コード」と呼ぶことも多い。
パット見わからないですが、実はかなり簡単なことなのです。
「あ」という文字をPCが認識するには0と1の組み合わせで表現しているのは何となく知っていると思います。そして「あ」という文字は以下のようにPCでは変換しています。
あ -> 11100011 10000001 10000010
この文字とビット列の対応関係のことを文字コードと呼びます。(意外と簡単!)
UTF-8やShift_JISが対応関係の種類というわけです。
さらに文字コードについて理解してみましょう。
文字をビット列にどうやって変換しているのか考えてみましょう。
ここでポイントとなるのが符号化文字集合と文字符号化方式の2つの言葉になります。
全く意味のわからない言葉です。ですので、以下の図で理解してみましょう。
あ = U+3042 -> 11100011 10000001 10000010
い = U+3044 -> 11100011 10000001 10000100
「文字集合」 -> 「バイト表現」
矢印の左側の文字とU+から始まる対応関係が符号化文字集合です。
そして、文字集合をバイト表現に変換する方式が文字符号化方式になります。
実はこれを理解することでUnicodeとUTF-8の関係が理解できるようになります。
Unicodeは符号化文字集合の対応関係のことです。(矢印の左側の対応関係)
そして、UTF-8は符号化文字集合をバイト表現に変換する文字符号化方式の1つの種類になります。
例えばUTF-8とUTF-16それぞれの文字符号化方式で「あ」を表現すると以下のようになります。
あ = U+3042 -(UTF-8)> 11100011 10000001 10000010
あ = U+3042 -(UTF-16)> 00110000 01000010
基本的に2進数だとバイトが長くなるため、16進数で表現されます。
1バイトの前半4桁と後半4桁を16進数で表現すると以下のようになります。
あ = U+3042 -(UTF-8)> 11100011 10000001 10000010 -> E3 81 83
あ = U+3042 -(UTF-16)> 00110000 01000010 -> 3042
もう一度定義を確認すると「コンピュータ上で文字(キャラクタ)を利用する目的で各文字に割り当てられるバイト表現」という説明が理解できると思います!
なぜ文字化けが起きるのか
ここまで理解できた方は文字化けをする理由がすぐに分かると思います。
UTF-8で「あ」という文字は「E3 81 82」で表現されていましたよね。
例えばUTF-8で書かれたファイルをShift_JISで読み込もうとすると「縺」という文字になってしまいます。
Shift_JISでは「縺」は「E3 81」になります。
ですので、最初の2バイトがShift_JISでマッチしてしまうため文字化けという現象が起きてしまうのです。
正直、ここはなんとなくの理解でいいと思いますが、IT素人にドヤ顔で説明できるようになれます。
また、phpやRubyでcsv出力を何も考えずにするとUTF-8で出力されます。
それをExcelで開くと文字化けしちゃうんですよ、、
その対策方法はもう少し下で説明したいと思います。
BOMとは
まずは結論からいきます。
BOMとはバイトオーダーマークの略称で、Unicodeで書かれた文書に記載される短い符号のことです。
簡単に言うと、PC内部でこのテキストファイルはUnicodeですよ〜と宣言するものになります。
ただ、最近はBOMを必要とする機会が少なく、BOMなしのUTF-8でも動作するように作られたアプリケーションが多いようです。
じゃあ別にBOMなんて意識しなくていいじゃんとなると思います。
しかし、我々プログラマーはBOM付きUTF-8を使用することで、Excel出力時の文字化けのリスクを減らすことができます。
PHPやRubyでcsvファイルを作成して、Excelを開くと何もしない場合は文字化けするリスクがあります。
phpがcsvファイルを作るとき->UTF-8でcsvファイルを作成する
Excelがcsvファイルを読み込んで表示するとき->Shift_JISで表示する
こんな違いがあるため、phpにおけるcsv出力辺りは文字化けのリスクが高いです。
解決策として、csv出力時にShift_JISで作成するというものがあります。
phpでは以下のように簡単に文字エンコーディングを変えることができます。
$value = mb_convert_encoding($recordValue, "SJIS", "UTF-8");
ただ、他のアプリケーションはUTF-8が主流ですので、できればUTF-8で出力したいですよね。でもExcelはShift_JISだし、、
行き詰まったときに登場するのがBOM付きのUTF-8です。
なんとExcelはShift_JISだけではなく、BOM月のUTF-8であればUTF-8でも正しく認識してくれます。
BOM付きのUTF-8でcsvファイルを作成するのが一番スマートではないかと思います。
BOMについては以上になります!
最後に
今回は文字コードの話から、BOM、そしてプログラミングでcsv出力をするときの注意点について書いてみました。
BOMの存在や、文字コードについて知らないとバグを治すのに時間がかかってしまうかもしれません。
そんなことがないように、少しでも今回の記事がお役に立てれたらなと思っています!
ここまで読んでくださった読者様ありがとうございました!
Discussion