文字コードとは、文字とコンピュータが扱える数値(バイト列)を対応づけるためのルールです。と、一言で言ってもその奥深さは伝わらないと思うので、このページでは知っているようで実はあまり知らない「文字コード」の基本知識を0か10まで順を追って解説します。
文字コードが必要な理由
コンピュータの中は「0と1」だけ
私たちが普段目にしている「文字」はコンピュータ内部ではそのままの形を認識しているわけではありません。コンピュータが実際に扱えるのは、0と1のビット情報(電気信号)だけです。
つまり、人間にとって分かりやすい「文字」をコンピュータが理解するには、何らかの方法で文字を数値データ(ビット列)に変換する必要があります。
たとえば、画面に映った「A」をコンピュータが処理するときには、「A」という文字を01000001
(2進数)として認識し、内部的には10進数の65や16進数の0x41といった表現で取り扱います。
この「文字」⇔「数値」を対応づけるルールをきちんと決めておかないと、コンピュータは文字を正しく理解できません。
文字と数値を結びつける「約束事」が文字コード
上で述べたように、文字と数値の対応関係を規格として定めたものが、いわゆる「文字コード」です。
もし文字コードが存在しないと、あるバイト列が何を表すのか、コンピュータも私たちも分からなくなってしまいます。
こうした仕組みがあるからこそ、私たちはテキストを保存し、読み込み、ネットワークで送信し、さらには画面に表示することができるのです。
ASCII・Shift_JIS・Unicodeの歴史
ASCII(アスキー)の誕生と限界
文字コードの代表格として最初に挙げられるのが、ASCII(アスキー)コードです。これは主に英語圏でコンピュータが使われ始めた頃に作られた規格で、7ビット(0~127)の範囲で英数字や記号を表します。
「英語だけじゃなく、日本語など他の言語もコンピュータで扱いたい」という需要が高まるにつれ、ASCIIコードだけでは不便が生じるようになりました。
日本語のためのShift_JIS
日本でコンピュータを普及させるには、日本語を入力・表示できなければなりません。しかし、ASCIIには日本語を表現する枠がありませんでした。そこで登場したのがShift_JIS(シフトJIS)です。
世界中の文字をまとめるUnicode
インターネットが普及し始めると、英語・日本語以外の文字も自由にやり取りしたいという需要が一気に高まりました。そのときに注目されたのがUnicode(ユニコード)です。
Unicodeは、世界中で使われているほぼすべての文字を1つの大きな文字セットとして定義することを目指した規格です。
Unicodeとは何か
文字セットとしてのUnicode
まず、Unicode自体を「文字コードの一つ」と表現することもよくありますが、より正確には「世界中の文字にコードポイントを割り当てた大きな文字セット」としてとらえるのが妥当です。
つまり、Unicodeとは「どの文字をどの番号にするか」を決めているのですが、そこから実際にバイト列に変換する方法(エンコーディング)は別で決められています。
コードポイント(U+XXXX)の仕組み
Unicodeで、各文字には「U+XXXX
」という形の番号が割り当てられます。
例えば、
- "A" →
U+0041
- "あ" →
U+3042
- "漢" →
U+6F22
このように、文字ごとに重複しない一意のコードポイントを設定しているのです。
ただし、実際にファイルやネットワークでやり取りするときは、「U+XXXX」のままではなく、必ずバイト列に符号化(エンコード)されるという点がポイントです。
Unicodeの注意点(私用領域・互換性など)
「Unicodeなら世界中の文字が何でも表せる!」というイメージはありますが、実際には以下のような留意点があります。
それでも、従来の文字コードと比べて圧倒的に多くの文字を標準化しているのが、Unicodeの強みです。
エンコーディングを理解する
文字セットとエンコーディングの違い
ここで重要なのが、「Unicode」と「UTF-8」などのエンコーディング方式は別物だという点です。
- Unicode … 世界中の文字を一覧としてまとめた「文字セット」
- エンコーディング(符号化) … 文字セットの各コードポイントを、実際のバイト列(0と1)に落とし込む仕組み
よく「Unicodeで書かれたファイル」という言い方をしますが、正確には「Unicodeの文字を何らかのエンコーディング(例:UTF-8)でバイト列化したファイル」です。
代表的なエンコーディング方式
UTF-8
- 可変長方式で、1文字を1~4バイトで表現する。
- ASCII範囲の文字は1バイトのままなので、古い英語圏のシステムとの互換性が高い。
- ウェブやプログラミング言語のソースコードなどで、現在もっとも普及している。
UTF-16
- 2バイト(16ビット)を基本単位とする。ただし、すべての文字を2バイトだけで表せるわけではなく、一部の文字はサロゲートペアを用いて4バイトになる。
- Windowsの内部APIや一部のプログラミング言語実装でよく使われる。
- バイトオーダー(ビッグエンディアン/リトルエンディアン)の問題があるため、BOM(後述)で区別することが多い。
UTF-32
- 常に4バイト(32ビット)で1文字を表す。
- 可変長ではないため解析はしやすいが、その分データ量が増えてしまう。
- 外部でのファイル保存や通信で使われることはあまり多くない。
可変長エンコードと固定長エンコード
エンコーディング方式には、可変長と固定長という2つの考え方があります。
- 可変長 … UTF-8のように、文字によって使うバイト数が異なる。ASCIIなら1バイト、中日韩の文字なら3バイト、など。
- 固定長 … UTF-32のように、常に4バイトを割り当てる。UTF-16は基本2バイトですが、一部例外として4バイトになるので「擬似的固定長」ともいえます。
可変長のほうがデータサイズを抑えやすい反面、文字列操作がやや複雑になります。固定長はシンプルですが、バイト数がかさむというデメリットがあります。
BOM(Byte Order Mark)とは
- BOM(Byte Order Mark)は、ファイルの先頭に付加して「このテキストはUTF-16のビッグエンディアンです」「リトルエンディアンです」といった情報を知らせるための仕組みです。
- UTF-8にもBOM付きの形式が存在し、ファイルの最初に
EF BB BF
という3バイトが入る場合があります。 - ただし、UTF-8でのBOMは必須ではなく、使わない方が好まれることも多いです。BOM付きUTF-8だと、ソフトによっては文字列の先頭に不可解な文字が表示されるなどの不具合が起きることがあります。
UTF-8の特徴とメリット
ASCIIとの互換性
UTF-8では、U+0000~U+007F(ASCII範囲)の文字は、そのまま1バイトで表せます。たとえば"A"は0x41のままです。
これは、古いシステムやプロトコルがASCIIを前提としているケースともスムーズに連携できるという大きな利点となります。
多言語対応のしやすさ
世界中の文字を扱うUnicodeを、バイト列として効率的に取り扱えるため、1つのファイルや文書で日本語、英語、中国語、韓国語、さらにロシア語やアラビア語まで混在させることも可能です。
ウェブページでも多国籍なコンテンツが当たり前に表示されるのは、UTF-8の普及が大きく寄与しています。
現代の標準としての普及
- HTML5やCSS、JavaScriptなどの仕様でも、文字コードはUTF-8を使うことが推奨・基本設定として定められています。
- PythonやRubyといったプログラミング言語のソースファイルも、UTF-8で書くのが事実上の標準となりました。
- こうした流れにより、「文字化けを避けるならUTF-8」という認識は、世界中で広まっています。
Shift_JISとUnicode(UTF-8)の比較
カバー範囲の違い
もし英語や日本語以外の文字を扱う必要が出てきたら、Shift_JISだと文字化けしてしまいます。一方、UTF-8なら問題なく表現できる可能性が高いという大きな違いがあります。
Shift_JISとUnicode(UTF-8)の整理
✅ Shift_JISは「日本語の文字セット」と「エンコーディング」がセットになった規格
✅ Unicodeは「文字セット」、UTF-8はそれをエンコードする方式
項目 | Shift_JIS | Unicode | UTF-8 |
---|---|---|---|
文字セット | 日本語(ASCII+JIS X 0208) | 世界中の文字(Unicode) | なし(Unicodeをエンコードする方式) |
エンコーディング | 1バイト or 2バイトの組み合わせ | なし(エンコーディングは別) | 可変長(1~4バイト) |
特徴 | 日本語専用・互換性が低い | 文字を統一する世界標準 | Unicodeを効率的にバイト列化 |
例 | 「A」= 0x41 / 「あ」= 0x82A0 | 「A」= U+0041 / 「あ」= U+3042 | 「A」= 0x41 / 「あ」= 0xE3 0x81 0x82 |
- Shift_JISは「日本語の文字セット」+「バイト列のエンコーディング方式」を含む「文字コード」
- Unicodeは文字セットだけで、実際にデータとして保存・送信するにはUTF-8などのエンコーディングが必要
- UTF-8はUnicodeをバイト列化するエンコーディング方式であり、単体では文字セットを持たない

この整理なら、Shift_JISは「セット」なのに対し、UnicodeとUTF-8は別物だと明確に分かりやすくなると思います!
文字化けが起こる仕組み
例えば、あるファイルが実はShift_JISで保存されているのに、テキストエディタやシステム側が「これはUTF-8だ」と思い込んで解釈すると、ズレが生じて画面上に「??」や「�」のような表示になることがあります。
逆の場合も同じで、UTF-8ファイルをShift_JISとして読み込めば文字化けするでしょう。
文字コードを明確に指定せずにデータをやり取りすると、こうしたトラブルは頻繁に起こり得ます。
機種依存文字への対処
日本語環境では、いわゆる機種依存文字がShift_JIS上で独自に割り当てられていたことがあり、Unicodeに取り込まれていなかったり、取り込まれていても別のコードポイントだったりします。
これが原因で、文字コード変換するときに「元の文字」が失われてしまう問題も起こります。
文字化けの原因と解決策
保存時と読み込み時の不一致
文字化けの最も典型的なケースが、ファイルを保存する際の文字コードと、読み込むときに使われる文字コードが合っていないというパターンです。
ファイルシステム自体には「このファイルはUTF-8で書かれている」などと明示的に保存される仕組みがないので、テキストエディタなどは推測で判断するか、設定で明示的に指定するしかありません。
推測が外れると文字化けします。
ツール設定やシステム間のズレ
実践的な対処法
- 使用するエディタやシステムで文字コードを明示する
- Visual Studio Codeやサクラエディタなどでは、ファイルの文字コードを明示的に指定・変更できます。
- 「保存するときはUTF-8」「読み込むときもUTF-8」とそろえるだけで、文字化けをかなり防げます。
- ウェブやメールなら、文字コードの宣言をしっかり行う
- HTMLなら
<meta charset="UTF-8">
を入れる。 - HTTPヘッダやメールヘッダでも「Content-Type: text/html; charset=UTF-8」のように宣言する。
- ブラウザやメールソフトは、宣言に合わせて正しく文字を表示します。
- HTMLなら
- できるだけUTF-8に統一する
- 既存のレガシーシステムを除いて、新しいプロジェクトやテキストファイルはUTF-8を使えば混乱が減ります。
- 無理にShift_JISで運用し続けると、多言語化や外部サービス連携などで後々大きな制限が出る可能性が高いです。

今ではほとんどのプログラムやウェブサイトがUTF-8を使っているため、文字コードのトラブルは昔ほど顕在化しなくなってきました。それでも、過去から続いているシステムや特定の環境では、依然としてShift_JISなどが残っていることも多いです。
そうした場面に遭遇したとき、今回の内容を思い出して、「どの文字コードで書かれ、どの文字コードで読もうとしているか?」 を確認してみましょう。きっとスムーズに対処できるはずです。