データ移行で文字化けするのはなぜ?Shift_JIS・CP932・外字の違いを数えた
データ移行の文字化けは、移す前と後で文字コードの表が違うために起きます。Pythonで数えると、WindowsのShift_JIS(cp932)にしかない字が454字、外字の領域が1,880字ありました。髙・﨑・①・㈱や社内で作った外字が、移した先で「?」や別の字になります。Access引越しでは、移す前に化けそうな字を数えてから移します。(2026年10月時点)
全体の流れと費用はAccess・オフコンの引越しのページにまとめています。
要点
- データ移行の文字化けは、移す前と後で文字コードの表が違うために起きます。
- Python 3.14.2で数えると、shift_jisで書ける字は6,944、cp932は9,280でした。
- cp932だけにある字は454字で、そのうち360字が髙・﨑などの漢字です。
- 外字の領域F040〜F9FCは1,880字分あり、どの字かは元のPCの外字フォントで決まります。
- 移す前にCSVの中の外字・cp932だけの字・書き換わる字を数えれば、直す字の一覧が作れます。
目次
データ移行で文字が化けるのは、なぜですか?
移す前と後で、文字コードの表が違うためです。古いAccessやオフコンから書き出したCSVは、Shift_JIS系の表で書かれていることが多くあります。一方、新しい仕組みはUTF-8で読むのがふつうです。2つの表のどちらにも無い字や、同じ番号に別の字を割り当てている字が、移した先で「?」や別の字になります。
化け方は、次の4つに分かれます。数はPython 3.14.2のcodecsで数えた計算値です。
| 化け方 | 例 | 移すと起きること | 数 |
|---|---|---|---|
| cp932だけにある字 | 髙 﨑 ① Ⅱ ㈱ № | shift_jisとして読むと「?」になる | 454字 |
| 外字 | 社内で作った人名の字 | 私用領域の番号だけ移り、字が分からなくなる | 領域は1,880字分 |
| 書き換わる字 | 〜 − ‖ ¢ £ ¬ | 似た別の字(~ - ∥ など)に変わる | 6か所 |
| cp932で書けない字 | 𠮷 鷗 絵文字 | Shift_JISの仕組みへ戻すときに止まる | 表の外 |
Accessの中は、MicrosoftのドキュメントによるとUnicodeで文字を持っています。化けるのは、CSVに書き出すときと、新しい仕組みがそのCSVを読み込むときです。
Shift_JISとCP932は、どれくらい違うのですか?
書ける字の数が2,336字違います。U+0080〜U+2FFFFの字を1字ずつ符号化して数えると、shift_jisは6,944字、cp932は9,280字でした。名前はどちらも「Shift_JIS」と呼ばれがちですが、Pythonでは別の表として扱います。
cp932はWindowsのShift_JISで、shift_jisは元の規格の表です。Pythonでは「ms932」「windows-31j」もcp932と同じ表を指します。差の内訳は、cp932だけにある字が454字、私用領域が1,884字です。逆にshift_jisだけにある字は「¥」(U+00A5)と「‾」(U+203E)の2字でした。
454字の中身を分けると、漢字が360字でいちばん多く、髙・﨑・德・隆などの人名・地名によく出る字が入ります。残りは㈱や㎡などの単位が36字、①〜⑳が20字、ローマ数字が20字、№や℡などの記号が18字です。得意先マスタや社員の台帳ほど、この454字に当たりやすくなります。
外字は、なぜ移すと字が分からなくなるのですか?
外字は字の形ではなく、番号だけがデータに入っているためです。cp932の外字の領域は0xF040〜0xF9FCです。ここはUnicodeの私用領域U+E000〜U+E757の1,880字に対応します。Pythonで0xF040を読むとU+E000、0xF9FCを読むとU+E757になりました。
その番号にどんな字を描くかは、元のPCに入っている外字フォントが決めています。Microsoftのドキュメントも、外字や私用領域の字はPCごとに割り当てが違うと書いています。割り当てが無いこともあります。新しい仕組みに番号だけ移しても、同じフォントが無ければ空白や四角で出ます。
外字は消さずに、次の順で一覧にします。
- データの中の私用領域の字を数え、番号ごとに何件あるかを出す
- 元のPCの外字フォントで、その番号に描かれた字を確かめる
- 番号ごとに、Unicodeにある字(例:髙)へ置き換えるか、新しい仕組みで外字として扱うかを決める
「〜」や「−」が別の字に変わるのは、なぜですか?
同じバイトに、shift_jisとcp932が別の字を割り当てているためです。2バイトの範囲を全部読み比べると、違うのは6か所でした。たとえば0x8160は、shift_jisでは「〜」(U+301C)、cp932では「~」(U+FF5E)になります。
見た目はほぼ同じでも、Unicodeでは別の字です。「10/15〜10/16」で検索しても、移した後のデータが「~」なら当たりません。品名や備考を突き合わせるときに、件数が合わない原因になります。
この6か所は、Pythonの表での結果です。製品によって表は少し違います。MySQLのドキュメントによると、0x815Fはsjisなら「\」(U+005C)、cp932なら「\」(U+FF3C)になります。移行先の製品で1件ずつ試すのが確実です。
移す前に、化けそうな字をどう数えればよいですか?
書き出したCSVを1字ずつ調べ、外字・cp932だけの字・書き換わる字・cp932で書けない字の4つに分けて数えます。私はこのためのスクリプト scripts/figs/mojibake_count.py を使っています。お使いのPCの中だけで動き、データを外に送りません。
def kind(ch):
o = ord(ch)
if o < 0x80: return None
if 0xE000 <= o <= 0xF8FF: return '外字'
if ch in SIX or ch in SIX.values(): return '書き換わる6字'
if not can(ch, 'cp932'): return 'cp932で書けない'
if not can(ch, 'shift_jis'): return 'cp932だけ'
架空の得意先マスタ10行で試しました。外字が2回、cp932だけの字が7種類、書き換わる字とcp932で書けない字が3種類ずつ見つかりました。結果には、字ごとに最初の出現位置(行と列)が出ます。この一覧が、そのまま「直す字の表」の下書きになります。
限界もあります。数えられるのはPythonの表で判定できる範囲です。外字が本当はどの字かは、元のPCのフォントを見ないと分かりません。オフコンの独自の文字コードは、CSVに書き出した後のデータで数えます。
このサイトで相談するには?
文字化けが心配なデータも、お見せいただかなくて構いません。何をどう頼むか決まっていなくても大丈夫です。
Access引越しが今の仕組みをうかがい、御社のやり方に合わせて、進め方を一緒に考えます。準備は要りません。無料で相談するからお声がけください。
よくある質問
- 移行先をUTF-8にすれば、文字化けは起きませんか?
- いいえ、外字は残ります。UTF-8は髙や﨑を持てますが、外字は私用領域の番号のまま移るので、元の字に置き換える一覧が要ります。
- 外字が何字あるかは、どこで分かりますか?
- データの中の私用領域U+E000〜U+F8FFの字を数えれば分かります。元のPCの外字フォントを開くと、その番号に描かれた字も確かめられます。
- Shift_JISの仕組みへ戻すときも気をつけますか?
- はい。𠮷・鷗・絵文字はcp932に無いため、書き出しが止まるか「?」になります。戻す前に同じスクリプトで数えておきます。
- データを外に出さずに数えられますか?
- はい。スクリプトはお使いのPCの中だけで動き、字の種類と行・列の位置を出すだけです。中身はどこにも送りません。
この数字の出し方
この記事の自前の数字は、次の見本・条件・回数で出しました。主宰が確かめ、更新日は2026年10月17日です。スクリプトの名前から、同じ手順を自分のファイルで再現できます。
- Access引越しの計算(2026年10月16日、Python 3.14.2 の codecs で1字ずつ符号化。shift_jis 6,944字・cp932 9,280字)。scripts/figs/mojibake_count.py
出典
- Python 標準ライブラリ codecs(標準エンコーディング cp932・shift_jis、エラーハンドラ)(2026年10月16日確認)
- Microsoft Learn「End-User-Defined and Private Use Area Characters」(2025年3月更新)(2026年10月16日確認)
- Microsoft Learn「EUDCCodeRange」(932=F040-F9FC、Unicode=E000-F8FF)(2026年10月16日確認)
- Microsoft Learn「About compressing the data in a Text, Memo, or Hyperlink field」(Access は Unicode で文字を持つ)(2026年10月16日確認)
- MySQL 8.0 リファレンスマニュアル 10.10.7.1「cp932 文字セット」(2026年10月16日確認)