出力したCSVをその場で開いて、文字化けや桁の欠けがないかを一件ずつ静かに確かめている開発者

AIに書かせたCSV出力|文字化けと桁ズレを防ぐ確認手順

「CSV出力の処理、書いておいて」——AIにそう頼んで、出てきたコードを読んで、テストデータで動かして、問題なし。そこまでは、いつもどおりでした。

問題が出るのは、たいてい何日か経ってからです。お客さんから「ファイルが文字化けしていて読めません」と連絡が来る。あるいは、経理の担当者から「電話番号の頭の0が消えているんですけど」と言われる。慌てて自分の環境で開き直すと、何ともない。自分の画面では、ちゃんと正しく見えている。

この「手元では合っているのに、相手の画面では壊れている」は、CSVで最も起きやすい事故です。そして、あなたの確認が甘かったからではありません。CSVは見た目がただのテキストなので、壊れていても壊れているように見えない。そのうえ、AIには「このファイルを誰が、何で開くのか」という肝心の前提が渡っていない。だから、どこの国でも通じる無難なコードが返ってくるだけなのです。

結論:AIに書かせたCSV・帳票の出力は、次の順に見ると事故がぐっと減ります。①「誰が何で開くか」から文字コードを決める(相手が日本の業務現場でExcelなら、BOM付きUTF-8が無難)。②区切り・改行・引用符のエスケープが仕様どおりか確かめる——カンマや改行を含むデータで一度壊してみるのが早いです。③Excelで化けやすい3つの値(先頭ゼロ・けた落ち・日付化)を守る。④先頭が = + - @ の値を無害化する(開いた瞬間に数式として動くことがあります)。⑤最後に、実データに近い1件を実際に相手と同じ手順で開いてみる。コードを読むより、1回開くほうが確実です。

一度に全部やらなくて大丈夫です。今日は、直近でAIに書かせたCSV出力を1つ開いて、encoding の指定があるかを見るだけでも十分です。そこが空欄なら、それだけで一番大きな穴がひとつ塞がります。

なぜAIのCSV出力は「手元では通る」のか

まず、いま何が起きているのかを整理させてください。

AIがCSVの書き出しを書くとき、渡されていない情報が3つあります。このファイルを誰が開くのか。何のアプリで開くのか。中にどんな値が入るのか。 この3つがないと、いちばん短くて素直なコードが返ってきます。文字コードの指定がなく、値はそのまま並べる、シンプルなコード。これは間違いではありません。前提のない場所では、それが正解だからです。

そして、そのコードはあなたの環境では正しく動きます。開発機の既定の文字コードはたいていUTF-8で、テストデータには日本語の氏名や長い数字がそこまで入っていない。だから通ってしまう。

ずれるのは、その先です。

どれも、AIの能力の問題ではありません。人間の開発者に「CSV出力を書いておいて」とだけ頼んでも、まったく同じものが上がってきます。前提が渡っていないだけ。だから、直す場所は出力コードではなく、頼み方と確認の順番です。

① 文字コードは「誰が開くか」から決める

最初に決めるのは、技術的な好みではなく受け取る人の環境です。

大事なのは、どれが正解かではなく、決めてから書かせることです。決めずに書かせると、AIは環境依存の既定値のまま出します。そして環境依存の既定値は、本番のサーバーとあなたのPCで違うことがあります。

もうひとつ、地味ですが効くのが改行の扱いです。Pythonの標準ライブラリでCSVを書くときは、ファイルを開く側で newline="" を指定します。これがないと、環境によっては改行が二重になり、1行おきに空行が入ったファイルができあがります。AIはこの指定を落とすことがあるので、レビューで見る価値があります。

② 区切り・改行・引用符のエスケープを確かめる

CSVは「カンマで区切るだけ」に見えて、実は取り決めがあります。よく使われるRFC 4180という取り決めでは、次のようになっています。

言語標準のCSVライブラリを使っていれば、ここは自動で面倒を見てくれます。危ないのは、AIが「その場で文字列を組み立てる」書き方を出したときです。",".join(values) のような一行は、読みやすくて速くて、そして値にカンマが入った瞬間に列がずれます。ずれた行だけが壊れるので、100件中3件だけおかしい、という気づきにくい形で出ます。

確かめ方は簡単です。わざと壊れるデータを1件混ぜて、書き出して、読み戻す。

この4件を通して、書き出したファイルを同じプログラムで読み戻したとき、元と同じ値に戻れば合格です。この「書いて、読み戻して、一致を見る」確認は、生成コードをそのまま使わない|最低限の動作確認の型で書いた考え方と同じで、CSVでは特によく効きます。目で見ても壊れが分からないぶん、機械に往復させるのが確実です。

なお、こういう「意地悪なデータ」を考えること自体を、AIに手伝ってもらうこともできます(AIにテストの境界値・異常系を洗わせる)。ただし出てきた候補は、自分の業務データに実際にありそうかで選び直してください。現場にない値を100件試すより、ありそうな4件のほうが役に立ちます。

③ 表計算ソフトで化ける3つの値を守る

ここからは、ファイルは正しいのに、開くと違って見える話です。切り分けの意味でも、この3つは覚えておく価値があります。

書き出したファイルの中では正しい値が、表計算ソフトで開くと先頭ゼロの消失・けた落ち・日付への変換という3つの形で変わってしまうことを並べた図
どれもファイルは正しい。変わっているのは「開いたあと」の見え方のほう

先頭ゼロ:0120-... の電話番号、007 のような枝番、先頭が0の郵便番号や社員番号。表計算ソフトはこれを数値と見なして、先頭のゼロを落とします。ファイルの中には残っているのに、画面からは消える。

けた落ち:桁数の多い数字は、表示が指数表記(1.23457E+11 のような形)に変わったり、有効桁の上限を超えた部分が0に置き換わったりします。会員番号や取引IDのような計算しない数字ほど、桁が長くて危ない。

日付化:1-2 や 2-10 のような、ハイフンでつないだ短い記号。品番や部屋番号として入れたつもりが、開いた瞬間に日付として解釈されます。一度日付になると、元の文字列には戻せません。

守り方は、どちらの都合を優先するかで変わります。

近ごろの表計算ソフトには、こうした自動変換を抑える設定が入ってきていますが、相手のバージョンや設定は選べません。「向こうで設定してもらえば大丈夫」に寄りかからず、こちら側で出し方を決めておくほうが、結局は手間が少なくて済みます。

④ 先頭が = + - @ の値を無害化する

もうひとつ、見落とされやすいのに影響が大きいものがあります。セルの先頭が = + - @ などで始まっていると、表計算ソフトがそれを数式として解釈することがある、という性質です。

たとえば、ユーザーが入力したお問い合わせの本文や、自由記述の備考欄。そこに入った文字列がそのままCSVに出て、担当者がファイルを開いた瞬間に数式として動く。単に表示が壊れるだけのこともあれば、外部への参照を含む式が仕込まれていることもあります。利用者の入力した文字列が、そのまま別のソフトの命令として実行されるという点で、これは表示の問題ではなくセキュリティの問題です(一般に「CSVインジェクション」「数式インジェクション」と呼ばれます)。

AIにCSV出力を書かせて、この対策が最初から入っていることは、まずありません。頼まないと入らない種類の処理だからです。

対策は難しくありません。

数値として計算に使う列まで一律に加工すると、今度は受け取り側が困ります。対象は「人が自由に入力した文字列の列」だけ、と線を引くのが実務的です。この手の「AIは頼まれないと書かない安全側の処理」については、AI生成コードのセキュリティ確認|見落としやすい穴にも近い観点をまとめています。

⑤ 実データに近い1件を、相手と同じ手順で開く

ここまで整理しても、最後にひとつだけ、代わりのきかない確認があります。相手と同じやり方で、一度開いてみることです。

30秒で終わります。そして、この30秒で見つかる不具合は、リリース後に見つかると半日仕事になります。

もし社内に受け取り側の環境がないなら、「開いた画面のスクリーンショットを1枚だけ送ってください」と先に頼んでおくのも手です。相手にとっては数十秒の作業で、こちらは確信を持ってリリースできます。頼みにくく感じるかもしれませんが、後から直すやり取りのほうが、お互いずっと大変です。

AIに渡す前提の文例

書かせる前に、この程度を添えるだけで結果が変わります。コピーして、<> の中だけ埋めてください。

前提:
- 出力するのはCSV。受け取るのは<日本の業務担当者/別システム>で、<表計算ソフトで開く/プログラムが読み込む>。
- 文字コードは<BOM付きUTF-8 / BOMなしUTF-8 / Shift_JIS>。改行は CRLF。
- 標準のCSVライブラリを使い、自前で文字列連結しない。
- 値にカンマ・改行・ダブルクォートが含まれても壊れないこと(引用符で囲み、内側の引用符は2つ重ねる)。
- 次の列は文字列として扱う:<電話番号・会員番号・品番>。数値に変換しない。
- 利用者が自由入力する列(<備考・お問い合わせ本文>)は、先頭が = + - @ の場合に数式として解釈されないよう無害化する。
- 大量件数でもメモリに全件溜めない書き方にする。
- 使うのは <言語・バージョン> と <標準ライブラリ>。他のライブラリは追加しない。

最後の2行を忘れないでください。件数の前提がないと、AIは全件をメモリに読み込んでから書き出す素直なコードを出します。開発中の100件では快適に動き、本番の50万件で落ちます。前提の渡し方そのものはAIにコードを書かせる前に渡す前提と制約|伝え方の型に詳しくまとめました。

明日やること(小さく3つ)

全部を一度にやろうとすると重いので、まずこの3つから。

  1. 直近のCSV出力コードを1つ開いて、文字コードの指定を見る。指定がなければ、受け取る相手を思い浮かべて1つ決める。ここが一番大きな穴です。
  2. カンマと改行を含むデータを1件混ぜて、書き出して読み戻す。元の値に戻れば、エスケープは効いています。
  3. 自由入力の列が出力に含まれていないか確認する。含まれていたら、先頭が = + - @ の場合の扱いを決める。

チェックリスト(コピーして使えます)

AIに書かせたCSV・帳票の出力をレビューするときの確認項目です。一度に全部でなく、今日は使える所だけで十分です。

文字コードと改行:

エスケープと構造:

開いたときに変わる値:

安全性:

最後の確認:

最後に

CSVの不具合は、報告のされ方がいつも少しつらいものです。「文字化けしています」「数字が違います」——こちらの手元では再現しないので、疑われている気持ちになりながら原因を探すことになる。しかも直してみれば、原因は1行の指定漏れだったりします。

出力したファイルを相手の担当者と一緒に画面で確かめ、問題なく開けたことに二人とも安心している場面

でも、それは腕の問題ではありません。CSVという形式が、壊れていることを見せてくれないというだけのことです。だから、見えないものを見えるようにする手順を、一度だけ用意しておけばいい。文字コードを決める。往復させて確かめる。相手と同じ手順で1回開く。この3つが習慣になると、あの気まずい連絡はぐっと減ります。

今日は、直近のCSV出力を1つ開いて、文字コードの指定があるかどうかだけ見てみてください。そこに一行足せた時点で、次のリリースはもう少し静かなものになります。焦らず、一つずつでいきましょう。

よければ、こちらも

関連用語