Shift_JIS と日本語の事情 — ダメ文字と CP932
Shift_JIS は 2 バイト目が ASCII の領域に食い込む設計。そこから生まれる「ダメ文字」問題と、半角カナ・CP932・今も現役である理由を構造から理解する。
「ソフト」と入力すると壊れる — 嘘のような本当の不具合
古い業務システムで「ソフト」という単語を保存すると、なぜかその行だけデータが崩れる。ファイルパスに「表」を含むフォルダを作ると特定のツールが失敗する。— Shift_JIS の現場には、こうした一見オカルトめいた不具合の言い伝えがあります。この章の目標は、これを構造から説明できるようになることです。
Shift_JIS は、Unicode より前の時代に「ASCII と共存しながら日本語を詰め込む」ために作られた符号化です。ASCII は 1 バイトのまま、全角文字は 2 バイトで表します。
問題は 2 バイト目の範囲です。0x40〜0x7E は、ASCII の英字や記号とまるごと同じ値。つまり全角文字の後半 1 バイトだけを取り出すと、ASCII の記号と区別が付きません。前章で見た UTF-8 の「多バイト文字の構成バイトはすべて 0x80 以上」という保証が、ここにはないのです。
「表」の 2 バイト目 0x5C は、ASCII ではバックスラッシュ。バイト単位で走査するプログラムには「表」の後半が記号に見えてしまいます。
ダメ文字 — 2 バイト目 0x5C の衝突
ASCII の 0x5C はバックスラッシュ \(日本語環境では円記号として表示されることも多い文字)です。多くのプログラミング言語や設定ファイルで「次の 1 文字を特別扱いする」エスケープ記号として使われます。
ここで Shift_JIS の「表」を見てみましょう。バイト列は 95 5C — 2 バイト目がちょうど 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 の構造の説明として正しいものはどれですか。
Shift_JIS は ASCII 互換を保ちながら 2 バイトで漢字を詰め込んだ設計ですが、2 バイト目に 0x40〜0x7E という ASCII の英字・記号と同じ値の範囲を使いました。つまり「全角文字の後半バイト」だけを見ると ASCII の記号と区別が付きません。UTF-8 のような「多バイト文字の構成バイトはすべて 0x80 以上」という保証がないことが、次の問題の伏線になります。
Q2. Shift_JIS で「表」は 95 5C の 2 バイトです。この文字を含む文字列を、0x5C をエスケープ記号(バックスラッシュ)として特別扱いする処理系に通すと壊れることがあります。理由はどれですか。
Shift_JIS を知らない(またはバイト単位で処理する)プログラムには、95 5C は「95 という何か」と「バックスラッシュ」に見えます。バックスラッシュを見つけると次の文字をエスケープとして消費するため、「表」の後半が食われ、以降の解釈が連鎖的にずれます。文字化けというより「データ破壊」に近い症状になるのが、このダメ文字問題の怖さです。
Q3. いわゆる「ダメ文字」に該当する例の組み合わせとして正しいものはどれですか。
2 バイト目が 0x5C(バックスラッシュ)になる文字が代表的なダメ文字で、「ソ」「能」「表」「十」「予」などが該当します。会社名やメッセージに普通に現れる文字ばかりなので、「ソフト」という単語で障害が起きる、といった一見不可解な不具合報告になります。ひらがなや英字が一律にダメなのではなく、たまたま 2 バイト目が記号の値に当たった文字だけが問題になる — 構造を知らないと絶対に推理できない現象です。
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 における半角カナ(アイウエオ…)の説明として正しいものはどれですか。
半角カナは電信・初期端末の時代から使われてきた 1 バイトのカナ(JIS X 0201 由来)で、Shift_JIS では 0xA1〜0xDF に 1 バイトで収められています。2 バイト文字の 1 バイト目(0x81〜0x9F, 0xE0〜0xFC)はこの領域を避けて配置されており、「Shift(ずらし)」という名前はこのやりくりに由来します。第 7 章では、UTF-8 を Shift_JIS で誤読したときに半角カナが混ざって見える理由としても再登場します。
Q5. CP932 と Shift_JIS の関係として正しいものはどれですか。
Windows の「Shift_JIS」の実体は CP932 という拡張版で、NEC・IBM 由来の機種依存文字(①、㈱、髙 など)が追加されています。同じ「Shift_JIS」を名乗っていても環境によって微妙に表が違うため、①を含むデータが別環境で化ける・変換に失敗するといった事故が起きます。「Shift_JIS と言われたら、実際は CP932 のことが多い」は実務で役立つ経験則です。
Q6. UTF-8 が標準になった現在も、Shift_JIS(CP932)を扱う場面が残っている理由として最も適切なものはどれですか。
文字コードの移行は「自分だけ変えれば済む」ものではなく、ファイルをやり取りする相手システム全体の足並みの問題です。Excel でダブルクリックで開かれる CSV、金融・行政系の固定長ファイル、古い POS や基幹システムなど、Shift_JIS 前提の連携は今も大量に稼働しています。だからこそ「受け取ったファイルがどちらの符号化か」を推理する技術(第 7 章)に実務価値があるのです。
この章で持ち帰ること
- 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 へ。今度は「バイト数」ではなく「文字数の数え方」が落とし穴になります。