合同会社小村ソフト
第 4 章

Shift_JIS と日本語の事情 — ダメ文字と CP932

Shift_JIS は 2 バイト目が ASCII の領域に食い込む設計。そこから生まれる「ダメ文字」問題と、半角カナ・CP932・今も現役である理由を構造から理解する。

「ソフト」と入力すると壊れる — 嘘のような本当の不具合

古い業務システムで「ソフト」という単語を保存すると、なぜかその行だけデータが崩れる。ファイルパスに「表」を含むフォルダを作ると特定のツールが失敗する。— Shift_JIS の現場には、こうした一見オカルトめいた不具合の言い伝えがあります。この章の目標は、これを構造から説明できるようになることです。

Shift_JIS は、Unicode より前の時代に「ASCII と共存しながら日本語を詰め込む」ために作られた符号化です。ASCII は 1 バイトのまま、全角文字は 2 バイトで表します。

ASCII
0x00〜0x7F の 1 バイト。英数字はそのまま
半角カナ
0xA1〜0xDF の 1 バイト(アイウエオ…)。電信時代からの資産
全角文字
1 バイト目 0x81〜0x9F, 0xE0〜0xFC + 2 バイト目 0x40〜0x7E, 0x80〜0xFC の 2 バイト

問題は 2 バイト目の範囲です。0x40〜0x7E は、ASCII の英字や記号とまるごと同じ値。つまり全角文字の後半 1 バイトだけを取り出すと、ASCII の記号と区別が付きません。前章で見た UTF-8 の「多バイト文字の構成バイトはすべて 0x80 以上」という保証が、ここにはないのです。

Shift_JIS の 2 バイト構造と、「表」= 95 5C の 2 バイト目 0x5C が ASCII のバックスラッシュと衝突する様子を示す図

「表」の 2 バイト目 0x5C は、ASCII ではバックスラッシュ。バイト単位で走査するプログラムには「表」の後半が記号に見えてしまいます。

ダメ文字 — 2 バイト目 0x5C の衝突

ASCII の 0x5C はバックスラッシュ \(日本語環境では円記号として表示されることも多い文字)です。多くのプログラミング言語や設定ファイルで「次の 1 文字を特別扱いする」エスケープ記号として使われます。

ここで Shift_JIS の「表」を見てみましょう。バイト列は 95 5C2 バイト目がちょうど 0x5C です。Shift_JIS を意識せずバイト単位で文字列を走査する処理系は、95 の次の 5C を独立したバックスラッシュと誤解し、さらに次のバイトをエスケープとして消費します。結果、「表」の後半が食われて文字が欠け、以降の解釈が連鎖的にずれる — 冒頭の「オカルト不具合」の正体です。

2 バイト目が 0x5C になる文字は「(83 5C)」「(94 5C)」「(95 5C)」「十」「予」「構」など多数あり、俗にダメ文字と呼ばれます。どれも日常語に普通に現れる文字なので、「特定の単語のときだけ壊れる」という再現条件の掴みにくい障害になります。0x5C 以外にも、2 バイト目が "(0x22)や |(0x7C)などに当たる組み合わせで同種の問題が起こり得ます。

小問 4-1 — 2 バイト構造とダメ文字

Shift_JIS の構造から、なぜ特定の文字だけがトラブルを起こすのかを導きます。

Q1. Shift_JIS の構造の説明として正しいものはどれですか。

Q2. Shift_JIS で「表」は 95 5C の 2 バイトです。この文字を含む文字列を、0x5C をエスケープ記号(バックスラッシュ)として特別扱いする処理系に通すと壊れることがあります。理由はどれですか。

Q3. いわゆる「ダメ文字」に該当する例の組み合わせとして正しいものはどれですか。

CP932 — 「Shift_JIS」を名乗る方言

もう 1 つの現場知識が機種依存文字です。丸数字の ①、㈱、ローマ数字の Ⅱ、「髙」(はしごだか)— これらは元の JIS 規格の文字集合にはなく、メーカーが独自に追加した文字でした。Windows はこれらを取り込んだ拡張版 CP932 を「Shift_JIS」として使っています。

つまり、世の中で「Shift_JIS のファイル」と呼ばれているものの多くは、正確には CP932 です。同じ名前を名乗る、微妙に違う表が複数ある — ①入りのデータを厳密な Shift_JIS として変換しようとすると失敗し、環境によって化ける文字が変わる、という厄介な事情の根です。「Shift_JIS がらみのトラブルでは、本当の表は CP932 ではないか」と一段疑うのが実務のコツです。

それでも Shift_JIS が現役である理由

Web の世界は UTF-8 にほぼ統一されました。それでも Shift_JIS(CP932)が消えないのは、符号化の移行が「自分だけ変えれば済む」問題ではないからです。ファイルをやり取りする相手 — Excel の従来形式 CSV、長年稼働する基幹システム、金融・行政系の固定長ファイル連携 — の足並みがそろわない限り、受け渡し部分には古い符号化が残り続けます。

だからこの講座では Shift_JIS を「過去の遺物」ではなく「今も推理の対象になる現役の容疑者」として扱います。UTF-8 のファイルを Shift_JIS として読む、Shift_JIS のファイルを UTF-8 として読む — この双方向の誤読パターンの見分け方は、第 7 章の総合演習の主役です。

小問 4-2 — 半角カナ・CP932・現役の理由

Shift_JIS まわりの実務知識を仕上げます。

Q4. Shift_JIS における半角カナ(アイウエオ…)の説明として正しいものはどれですか。

Q5. CP932 と Shift_JIS の関係として正しいものはどれですか。

Q6. UTF-8 が標準になった現在も、Shift_JIS(CP932)を扱う場面が残っている理由として最も適切なものはどれですか。

この章で持ち帰ること

  • Shift_JIS は ASCII 1 バイト + 全角 2 バイトだが、2 バイト目が ASCII の値域(0x40〜0x7E)に食い込む
  • ダメ文字 = 2 バイト目が 0x5C などの記号に当たる文字(ソ 83 5C・能 94 5C・表 95 5C など)。エスケープ処理と衝突してデータが壊れる
  • 半角カナは 0xA1〜0xDF の 1 バイト。Windows の「Shift_JIS」の実体は機種依存文字入りの CP932
  • Excel の CSV やレガシー連携のせいで今も現役。誤読パターンの推理対象として付き合いは続く

次章は Unicode 側のもう 1 つの符号化、UTF-16 へ。今度は「バイト数」ではなく「文字数の数え方」が落とし穴になります。