N2
NanToo
文字コード戦争 — Shift_JIS vs EUC-JP vs UTF-8、日本語Webが経験した混沌
DDEVELOPER
開発9 分で読める

文字コード戦争 — Shift_JIS vs EUC-JP vs UTF-8、日本語Webが経験した混沌

2026年の今、Webページの文字コードはUTF-8一択です。しかし2000年代まで、日本のエンジニアはShift_JIS・EUC-JP・ISO-2022-JP (JIS)という3つの文字コードを「使い分ける」必要がありました。Windows用にはShift_JIS、LinuxサーバーにはEUC-JP、メール送信にはISO-2022-JP — ひとつ間違えば文字化け。この記事では、日本語の文字コードがなぜ3つに分裂したのか、どんな地雷が埋め込まれていたのか、そしてUTF-8がどうやってこの混沌を終わらせたのかを辿ります。

#文字コード#Shift_JIS#EUC-JP#UTF-8#文字化け#絵文字
AD

始まり — JIS X 0208 が定めた「6,879文字」

日本語の文字コード史は、1978年のJIS C 6226(後のJIS X 0208)から始まります。この規格は日本語で必要とされる文字として6,879文字を「区点コード」という体系で定義しました。

規格文字数内容
JIS X 02011969191半角英数 + 半角カタカナ
JIS C 6226 (JIS X 0208:1978)19786,802第一・第二水準漢字、ひらがな、カタカナ、記号
JIS X 0208:198319836,87778JISからの字形変更(「薮」→「藪」等)問題発生
JIS X 0208:199719976,879最終版
JIS X 021219906,067補助漢字(EUC-JPで使用、Shift_JISでは使えない)

重要なのは、JIS X 0208は文字の集合と番号(区点コード)を定めただけで、コンピュータ上のバイト表現は規定していないという点です。この「番号はあるがバイト列が決まっていない」状態から、3つの符号化方式が生まれました。

Shift_JIS — Microsoftと「5C問題」の爆弾

Shift_JIS(正式にはJIS X 0208の附属書1で規定)は、1982年にアスキー社の技術者とMicrosoftが共同設計しました。設計の制約は厳しいものでした:

  • JIS X 0201の半角カタカナ(0xA1-0xDF)をそのまま残す
  • ASCIIの1バイト文字領域(0x21-0x7E)と重複しない
  • 当時のMS-DOSで動作すること

これらを満たすため、2バイト文字の第1バイトを0x81-0x9Fと0xE0-0xEFに、第2バイトを0x40-0x7Eと0x80-0xFCに割り当てました。この「シフト」が名前の由来です。

5C問題 — バックスラッシュの罠

Shift_JISの最大の構造的欠陥は、2バイト文字の第2バイトに0x5C(バックスラッシュ / ¥記号)が現れることです。影響を受ける漢字の一部:

文字Shift_JISバイト列第2バイト
0x95 0x5C0x5C = \
0x89 0x5C0x5C = \
0x90 0x5C0x5C = \
0x94 0x5C0x5C = \
0x83 0x5C0x5C = \

C言語やPerlでは0x5Cはエスケープ文字です。ファイルパスの区切り(Windows)でもあります。Shift_JISのテキストを1バイトずつ処理するプログラムは、「表」の第2バイトをバックスラッシュと誤認し、次のバイトをエスケープシーケンスとして食べてしまうのです。

「表示」「能力」「ソフト」— これらの日常的な単語がバグを引き起こすため、「ダメ文字」と呼ばれ、日本のプログラマの悩みの種でした。

EUC-JP — Unix世界の回答

EUC-JP(Extended Unix Code for Japanese)は、AT&TがUnix向けに設計した符号化方式です。設計思想はShift_JISと対照的でした:

  • 2バイト文字は第1バイト・第2バイトともに0xA1-0xFE(最上位ビットが常に1)
  • ASCIIの範囲(0x00-0x7F)と完全に分離
  • JIS X 0212(補助漢字)にも対応(3バイトシーケンス)

最上位ビットで1バイト文字と2バイト文字を区別できるため、5C問題は原理的に発生しません。grepやsedなどのUnixツールとの相性がよく、1990年代のLinuxサーバーやSolarisでは事実上の標準でした。

しかし問題もありました:

  • 半角カタカナに0x8E(SS2)プレフィックスが必要で2バイトになる
  • Windows上ではほぼ使われない(Windowsの内部コードはShift_JIS → UTF-16)
  • Webブラウザでの自動判別精度がShift_JISに劣ることがあった

結果として、サーバーサイドはEUC-JP、クライアント(ブラウザ)はShift_JISという分裂が生まれました。PHPのmb_convert_encoding()やPerlのEncodeモジュールが重宝された理由です。

ISO-2022-JP — メールという第三の戦場

電子メールにはさらに別の文字コードが使われていました。ISO-2022-JP(通称「JISコード」)は、RFC 1468 (1993) で定義された7ビット完結の符号化方式です。

なぜ7ビット? 1980-90年代のメールサーバー(MTA)には、8ビット目を勝手に落とす実装が存在しました。Shift_JISやEUC-JPは8ビットを使うため、そうしたサーバーを経由すると文字化けします。ISO-2022-JPはエスケープシーケンスで文字集合を切り替えることで、7ビットの範囲内ですべてを表現します。

ESC $ B  → JIS X 0208 (日本語) に切り替え
ESC ( B  → ASCII に切り替え

例: "Hello世界" の場合
Hello ESC$B @$3& ESC(B

RFC 2047 (MIME) によるヘッダーのBase64/Quoted-Printableエンコーディングと組み合わせ、日本の電子メールは2010年代までISO-2022-JPが標準でした。Gmailがメール送信にUTF-8をデフォルトにしたのは2012年頃のことです。

機種依存文字 — ①②③が化ける理由

「Windowsで作った文書をMacで開いたら①が(日)になった」— これが機種依存文字(プラットフォーム依存文字)の問題です。

原因は、Shift_JISの未使用領域(0xF040-0xFCFC、いわゆる「外字領域」)に、MicrosoftとAppleが異なる文字を割り当てたことです。

バイト列Windows (CP932)Mac (MacJapanese)
0x8740(未定義 or 別字形)
0x8741(未定義 or 別字形)
0x8754(未定義 or 別字形)
0x8790(未定義 or 別字形)

さらに、MicrosoftのShift_JIS実装であるCP932 (Windows-31J)は、JIS X 0208にない文字(①②③、㈱、㍉、ローマ数字など)を独自に追加しました。つまり「Shift_JIS」と「CP932」は厳密には別物です。

Webでcharset=Shift_JISを指定しても、ブラウザは実質的にCP932として解釈します。WHATWGのEncoding Standardでは、Shift_JISというラベルはCP932にマッピングすると明記されています。

絵文字の起源 — キャリア3社の独自拡張からUnicodeへ

1999年、NTTドコモのi-mode開発チームの栗田穣崇氏が、12×12ピクセルの絵文字176種を設計しました。携帯メールで感情を伝えやすくする目的でしたが、これが文字コードの新たな戦場を生みました。

au (KDDI) とSoftBank (旧Vodafone) も独自の絵文字を実装。3社の絵文字はコードも図柄もバラバラで、キャリア間メールでは変換テーブルが必要でした。変換できない絵文字は〓(ゲタ)に置換されました。

Unicode 6.0 (2010) — 絵文字の統一

GoogleのMark DavisMarkus Schererが2007年にUnicode Consortiumに絵文字の提案書を提出。Appleも賛同し、2010年のUnicode 6.0で722個の絵文字がUnicodeに正式収録されました。

2026年現在、Unicode 16.0には3,790以上の絵文字が収録されています。日本のガラケー文化が生んだ独自拡張が、世界標準になった稀有な例です。

文字化けの自動判定 — なぜ完璧にはならないのか

日本語の文字コード判定は確率的な推定であり、100%の正解は原理的に不可能です。理由は以下の通り:

  • Shift_JISとEUC-JPのバイト範囲が重なる領域がある
  • 短いテキスト(数文字)では統計的な判断材料が不足する
  • 半角カタカナのみのテキストはShift_JISとEUC-JPで区別できないケースがある

代表的な判定ライブラリとそのアプローチ:

ライブラリ手法特徴
ICU (CharsetDetector)バイト列パターン + 言語モデル最も高精度。Java/C++
nkf (Network Kanji Filter)バイト範囲 + ヒューリスティクス日本語特化。Perl/Ruby標準添付
chardet (Python)Mozillaのアルゴリズム移植多言語対応
jschardet / encoding-japaneseバイト統計ブラウザJS向け

これらのツールでも、例えば「カナ」の3文字だけを判定させると、Shift_JISともEUC-JPとも解釈可能なため誤判定することがあります。

UTF-8への大移行 — 何が変わったのか

2000年代後半から2010年代にかけて、日本のWebは段階的にUTF-8へ移行しました。主なマイルストーン:

出来事
2005Ruby on RailsのデフォルトがUTF-8 → 新規Webアプリの標準に
2007Google全サービスがUTF-8統一
2008HTML5仕様で <meta charset="UTF-8"> が標準化
2010WordPress 3.0がUTF-8デフォルト。日本語ブログの大半が移行
2012GmailがメールのUTF-8送信をデフォルト化
2015Windows 10のメモ帳がBOM付きUTF-8をデフォルト保存に
2019Windows 10 May 2019 Updateでメモ帳がBOMなしUTF-8デフォルトに
2024Web全体の98%以上がUTF-8 (W3Techs調査)

UTF-8がShift_JISとEUC-JPの両方を置き換えられた理由は明確です:

  • 5C問題がない — UTF-8の継続バイトは0x80-0xBFで、ASCII範囲と重複しない
  • 1つのコードで統一 — サーバー/クライアント/メール/DBすべてUTF-8にすれば変換が不要
  • 絵文字に対応 — Shift_JIS/EUC-JPではUnicode絵文字を表現できない
  • 国際化が容易 — 多言語混在テキスト(日英中韓混在)も1エンコーディングで完結

2026年でもShift_JISが残る場所

UTF-8がWebを制覇した2026年でも、Shift_JIS(CP932)が使われ続けている領域があります:

  • Windowsコマンドプロンプト (cmd.exe) — デフォルトのコードページは932 (Shift_JIS)。PowerShellやWindows TerminalではUTF-8がデフォルトになったが、レガシーバッチファイルはShift_JIS前提
  • CSVファイル — ExcelはBOM付きUTF-8でないとCSVを正しく開けない。多くの業務システムが「Excel互換」のためShift_JIS CSVを出力
  • 官公庁・金融のレガシーシステム — COBOLやメインフレームとの接続でShift_JISやEBCDICが健在
  • 一部のゲーム機・組み込み機器 — メモリ効率やレガシー互換でShift_JISを使用

新規開発でShift_JISを選ぶ理由は皆無です。既存システムとのインターフェースでやむを得ず変換が必要な場合にのみ、iconvやプログラミング言語の変換ライブラリを使いましょう。

まとめ

  • 日本語の文字コードはJIS X 0208(1978年)の文字集合を3つの方式で符号化したことから分裂が始まった
  • Shift_JIS: MS-DOS/Windows標準。半角カナ互換のため2バイト目に0x5C(バックスラッシュ)が出現する「5C問題」を抱える
  • EUC-JP: Unix/Linux標準。最上位ビットで1バイト/2バイトを区別でき安全だが、Windowsでは普及せず
  • ISO-2022-JP: メール標準。7ビット完結のためエスケープシーケンスで文字集合を切り替える
  • 機種依存文字: Shift_JISの未使用領域にMicrosoftとAppleが異なる文字を割り当て、クロスプラットフォームで文字化け
  • 絵文字: ドコモ・au・SoftBankの独自実装 → Unicode 6.0 (2010) で世界標準に
  • UTF-8がすべてを解決: 5C問題なし、変換不要、絵文字対応、国際化対応
  • 新規開発はUTF-8一択。レガシーとの接続のみ変換ツールを活用

参考文献・ソース

記事作成に関する注記

本記事は AI(大規模言語モデル)を編集補助として活用して作成しています。 公開前に編集者が内容を確認していますが、事実誤認・仕様の解釈ミス・最新情報との齟齬が含まれる可能性があります。 重要な判断を行う際は、本文中の一次ソースや公式ドキュメントを必ずご自身でご確認ください。 誤りにお気づきの場合は、お問い合わせフォームよりご連絡いただけると助かります。

🔧 関連ツール

📚 関連記事

AD