PR

CSVの文字化けを直す道具を作った(ただし、化けた画面をコピーして貼っても直りません)

CSVの文字化けを直す|AI部長マン アフィリエイトサイト制作

結論:CSVファイルを落とすだけ

置き場所はここ。

CSV文字化けお直し

やることは1つ。画面の枠にCSVファイルを落とす。それだけで文字コードを見分けて、中身を表で見せる。あとは保存先を3つから選ぶ。

  • Excelで開く用(UTF-8のBOM付き)
  • 基幹システムに入れる用(Shift_JIS)
  • Web・システム連携用(UTF-8のBOMなし)

ファイルはどこにも送っていません。変換は全部ブラウザの中で動きます。この点は後半で、確かめ方まで書きました。

電帳法リネーマー、インボイス番号チェッカーに続いて3本目です。並べてあるのは道具箱。

文字化けは「壊れた」のではなく、読み方を間違えているだけ

先に、いちばん大事なところを書く。

文字化けしたファイルを見ると、多くの人は「壊れた」と思います。しかし実際に起きているのは、同じバイトの並びを、違う辞書で引いているという現象だ。日本語のファイルは「あ」を 82 A0 と書く決まり(Shift_JIS)と、E3 81 82 と書く決まり(UTF-8)がある。書いた側と読んだ側で決まりが食い違うと、意味の通らない字が並ぶ。

だからファイルそのものは、たいてい無事なまま、そこにあります。読み方を教えてやれば元に戻ります。この道具がやっているのは、それだけです。

実測:画面をコピーした時点で、10件中8件は戻せなくなっていた

ここが、この記事でいちばん伝えたいところ。

化けた画面を見て、そこをコピーして「文字化け 直す」で出てくるサイトに貼る。よくやる手順です。しかし、これはたいてい失敗する。理由を実測しました。

日本語の文字列を10個用意して、UTF-8で書いたものをShift_JISとして表示させた。つまり、いちばんよくある化け方を再現した。結果はこうなりました。

元の文字列化けた見た目元に戻せるか
取引先名,金額蜿門シ募�蜷�,驥鷹。�戻せない
株式会社かすみ商店譬ェ蠑丈シ夂、セ縺九☆縺ソ蝠�コ�戻せない
日本語譌・譛ャ隱�戻せない
大阪府大阪市北区螟ァ髦ェ蠎懷、ァ髦ェ蟶ょ圏蛹コ戻せる
取引先蜿門シ募�戻せない
東京都千代田区一番地譚ア莠ャ驛ス蜊�サ」逕ー蛹コ荳�逡ェ蝨ー戻せない
あいうえお縺ゅ>縺�∴縺�戻せない
商品名,数量,金額蝠�刀蜷�,謨ー驥�,驥鷹。�戻せない
山田太郎螻ア逕ー螟ェ驛�戻せない
請求書隲区アよ嶌戻せる

10件のうち8件が戻せませんでした。

見分け方は簡単で、化けた文字列の中に「�」が混ざっているかどうか。上の表で戻せない8件には、すべてこれが入っている。よく見ると「蜿門シ募�蜷�」のように紛れ込んでいる。

この「�」は、読み方の辞書に載っていないバイトに出くわしたとき、ブラウザやアプリが「読めませんでした」という印として置く記号だ。ここで元のバイトは捨てられています。捨てられたバイトは、画面をコピーしても付いてこない。

だから化けた画面をコピーして貼る方法には、原理的に穴があります。一方、ファイルの中のバイトはまだ生きています。だからこの道具は、ファイルそのものを落としてもらう作りにした。

貼り付けの欄も残してあります。ただし開くと最初に「たいてい直りません」と書いてある。使えないものを使えるように見せるほうが、あとで困ることになります。

「機種依存文字だから落ちる」は、たいてい間違っている

もうひとつ、実測して分かったことがある。

①②㈱№℡Ⅰ髙﨑。この手の字は「機種依存文字」と呼ばれ、システムに取り込むと落ちると言われる。私もそう思っていました。

Shift_JISの変換表を総当たりで調べたところ、この8種類はすべてShift_JISに入っていた。①は 87 40、㈱は 87 8A、髙は EE E0、﨑は ED 95。ちゃんと居場所がある。

では何が落ちるのか。総当たりで調べて分かったのは、Shift_JISに入っていないのはこちらの字だということ。右の列(どこで生まれるか)は実測ではなく、調べた範囲です。

落ちる字正体どこで生まれるか
〜波ダッシュ(U+301C)Macで「から」を変換すると、この字になることがある
−マイナス記号(U+2212)数式用の記号。全角ハイフン「-」とは別の字
¥欧文の円記号(U+00A5)Windowsの「¥」とは別の字
絵文字全般ニコニコ顔などの絵文字備考欄に入ってくる
令和の合字(U+32FF)元号を1文字にまとめた字Shift_JISが作られたあとに増えた字

Macで作ったCSVがWindowsの基幹システムで落ちるとき、犯人は①ではなく「〜」であることが多い。見た目がほとんど同じ「~」(全角チルダ)はShift_JISに入っているので、置き換えればShift_JISに書き出せます。

ただし、ここも言い切らないでおきます。①や髙はShift_JISには入っているが、JISの基本の範囲からは外れた区画にある。受け取る側のシステムが対応していなければ、そこで落ちることはあります。Shift_JISに変換できた、と、相手のシステムで通る、は別の話だ。道具の画面では、この2つを分けて出すことにしました。

変換表を持たずに、ブラウザから逆引き表を作った

ここは仕組みの話なので、興味がなければ次の見出しまで飛ばしてほしい。

ブラウザはShift_JISを読むことができます。しかし書くことができません。書き出しの機能はUTF-8しか出せないと標準で決まっている(Encoding Standard/2026年8月30日 確認)。

そこでふつうは、変換表を持った外部ライブラリを読み込む。数百KBあります。今回は、それを入れたくありませんでした。外部から読み込むものが1つでもあると、「このページはどこにも送っていません」という説明が弱くなるからだ。

やったのは単純なことで、読めるほうの機能を1組ずつ引いて、逆向きの表をその場で作る。バイトの組み合わせを全部(11,280組)試して、出てきた字を控えておく。実測したところ、9,397文字の表が10ミリ秒ほどでできた(手元のMacで10回測って8〜12ミリ秒)。表を持ち歩くより軽い。

おかげでこの道具は、外部ライブラリを1つも読み込んでいません。単一HTML 1ファイルで65KB、圧縮すると21KBになる。1本目に作った電帳法リネーマーは、PDFを読む部品を抱えて1.5MB(1,580,765バイト)あった。圧縮前どうしで比べると、24分の1ほどです。

作った表が正しいかどうかは、全数で確かめました。表に入っている9,397文字を1本につないで変換し、読み直して元に戻るかを見る。9,397文字すべてが元に戻った。

読んで書き戻すと、バイトが変わる字が398通りある

全数調査をしていて、想定していなかったことが出てきました。

Shift_JISには、同じ字が2箇所に入っている組み合わせが398通りある。たとえば「≒」は 87 90 と 81 E0 の両方にある。読むときはどちらも「≒」になるが、書くときはどちらか一方を選ぶことになる。

つまり、Shift_JISのファイルを読んで、そのままShift_JISで保存し直すと、元のファイルとバイト単位では一致しないことがある。見た目も意味も同じなので実務ではまず気づかないが、ファイルのハッシュを取って照合するような使い方では問題になる。

この道具では、2箇所にある字についてJISの基本の範囲側を選ぶようにしました。拡張の区画を避けたほうが、受け取る側で落ちにくいからだ。そして「元ファイルとバイトを一致させたい用途には向かない」と画面に書きました。398という数も一緒に出してあります。

自分の作ったものの限界を書くのは気が進みませんが、書いていないと、あとで踏んだ人が原因にたどり着けません。

黙って文字を消さない

Shift_JISで保存するとき、変換できない字があったらどうするか。

変換ツールによっては「?」に置き換えるか、黙って取り除く。数百行のファイルで1文字がそうなっても、まず気づかない。気づくのは、取り込んだ先で誰かが困ったときです。

この道具は、書けない字が1つでもあったら保存せずに手を止める。そして何の字が、何個、何行目にあるかを表にして出す。見た目が同じ代わりの字があるものは提案する(〜なら~、−なら-)。それでも代わりがない字は、取り除いていいかを、もう一度たずねる。

黙って消すことだけはしません。ここは受け入れ検査にも入れてあって、保存ボタンを押しても実際にファイルが落ちてこないことを毎回機械で確かめています。

化けているかどうかの判定を、一度間違えた

作っている途中で、はっきり間違えた箇所があります。

最初は「化けているかどうか」を、日本語らしさで測っていた。ひらがな・カタカナ・漢字が多ければ日本語、少なければ化けている、という考え方だ。

これが通りませんでした。化けた文字列「螟ァ髦ェ蠎懷、ァ髦ェ蟶ょ圏蛹コ」を見てください。漢字です。文字の種類で数えると、化けた文字列のほうが「日本語らしい」と出てしまう。単体テストが落ちて気づきました。

考え直して、判定の軸を入れ替えました。使ったのは、こちらの性質です。

正常な日本語をShift_JISで書いたバイトの並びは、UTF-8としてはまず成立しない。 漢字の1バイト目は 81〜9F の範囲に来るが、UTF-8ではこの範囲は「文字の続き」を表すバイトで、先頭には来られないからだ。

だから、化けているように見える文字列をShift_JISのバイトに戻してみて、それがUTF-8として筋の通る並びになったなら、元はUTF-8だった証拠になる。見た目ではなく、成立するかどうかで判定します。これに変えたら通りました。

見た目で判断すると間違える、というのは今回に限った話ではありません。前に作った道具でも、画面の表示は3項目とも正しいのに内部の判定は間違っている、という状態を踏んだことがあります(電帳法リネーマーの記事に書いた)。

Excelが形を変えてしまう問題は、この道具では直らない

正直に書いておきます。

CSVを開くと郵便番号の先頭の0が消える。「1-2」が日付になる。13桁の番号が 8.70011E+12 になる。よくある困りごとですが、これは文字化けとは別の問題で、この道具では直らない。

ファイルの中身は正しい。Excelが開くときに、勝手に数値や日付として解釈しているだけです。だからファイルを何度変換しても直りません。Excelの「データの取得」から文字列として読み込むか、開かずに中身を確認する必要がある。

インボイスの登録番号がExcelで指数表示になって桁が落ちる話は、インボイス番号チェッカーの記事のほうで詳しく書いた。あちらは「桁が落ちた番号を見つけて名指しする」道具です。

ファイルを送っていないことの確かめ方

顧客名簿や取引先の一覧は、それ自体が個人情報であり営業秘密でもある。「送っていません」と書いてあるだけのサイトに落とすのは、正直こわい。

なので、確かめられるようにした。

  1. ネットを切ってから使ってみる。 ページを開いたあとにWi-Fiを切っても、変換も保存も同じように動く。送っているなら動かない。
  2. ブラウザの機能で、通信そのものを禁止している。このページは connect-src 'none' という宣言を持っていて、通信のしくみ(fetch・XHR・WebSocket・sendBeacon)がどれも使えない状態になっている。仮に送ろうとしてもブラウザが止める。
  3. 開発者ツールのネットワークを開いたまま使う。通信は1本も増えません。
  4. アクセス解析のタグも入れていない。上の通信禁止と両立しないからだ。

この3つはどれも受け入れ検査に組み込んであって、公開するたびに本物のChromeで実測している。ネットを切った状態でも判定と保存が同じように動くこと、fetchがブロックされること、sendBeaconがブロックされること、画像を使った持ち出しもできないこと、外に出ていったリクエストが0本であること。ここが1つでも崩れたら公開しません。

ファイルを保存して社内の共有フォルダに置いても同じように動く(ファイルとして開いた状態でも判定と保存が動くことを、受け入れ検査で確かめています)。そのほうが落ち着くなら、そうしてください。

使い方

  1. CSV文字化けお直しを開く
  2. CSVファイルを枠に落とす(クリックして選んでもよい)
  3. 判定と中身が出るので、表が日本語として読めているかを目で確かめる
  4. 保存先を3つから選ぶ

3番目を飛ばさないでほしい。文字コードの判定は、BOMという目印が付いているとき以外は推定になる。だから中身を必ず表で出すようにしました。日本語として読めていなければ、その判定は外れています。

この道具でやらないこと

  • 「�」になった文字は元に戻さない。 推測で埋めることもしない
  • 中身の意味は見ない。金額や日付が正しいかどうかは判定しない
  • 勝手に文字を置き換えない。提案はするが、決めるのは使う人
  • 通信しない。だから実在確認のような、外部に問い合わせる機能は作れない

実物のデータでは、まだ試していません

ここも正直に書きます。

この道具は、自分で作ったCSVと、実際に起きる化け方を再現したデータで検証した。単体で133件、本物のChromeで82件、合わせて215件の検査に通してある。公開したあと、本番のURLにも同じ検査をかけて78件合格を確認した(残りはローカルでしか測れない検査)。

ただし実物の顧客名簿や取引先マスタでは試していない。手元にある実データは扱いが難しく、道具のフォルダに置かないと決めているためだ。Windows版のExcelが出力したCSVでの確認もできていない(手元はMac)。

なので、もし「うちのファイルだと直らなかった」「この文字が落ちた」ということがあれば、お問い合わせから教えてほしい。ファイルそのものを送っていただく必要はありません。どんな見え方をしたかが分かれば、こちらで再現して直せる。

よくある質問

料金はかかりますか

かかりません。登録も不要。道具の画面には、広告も解析タグも入れていません。

ファイルは本当にどこにも送られませんか

送られません。上に書いた4つの方法で確かめられます。ページ自体が、ブラウザの機能で外部との通信を禁止した状態で動いています。

どの文字コードに対応していますか

UTF-8(BOMあり・なし)、Shift_JIS(CP932)、EUC-JP、UTF-16(LE・BE)を見分けます。書き出しはUTF-8のBOM付き・BOMなし、Shift_JISの3種類です。

「Shift_JIS」と「CP932」は違うものですか

厳密には違います。CP932はShift_JISに①や㈱、髙や﨑などを足したもので、Windowsで使われてきた形。この道具はCP932として読み書きします。日本の実務で「シフトJISで」と言われるときは、たいていCP932を指しています。

何行まで読めますか

1万行のファイルで動作を確認しています。ファイルサイズの上限は80MBにしてあります。ブラウザの中だけで動かすため。

化けた文字をコピーして貼る欄は、なぜ残してあるのですか

化け方によっては直せるからです。「�」が混ざっていない化け方(Web由来のCSVで起きる形)なら元に戻せます。ただし直せないことのほうが多いので、開いたときに先に警告が出るようにしました。

Excelで開くと先頭の0が消えます。これも直りますか

直りません。それはファイルの中身ではなく、Excelが開くときの解釈の問題です。この道具はファイルの中身を正しく保ちますが、Excelの読み方までは変えられません。

コメント

タイトルとURLをコピーしました