ファイルの中身は同じなのに一致しない原因|BOMと改行コードの早見表と確認手順

同じに見える2つのファイルを見比べている様子のイラスト トレード自動化実録

コピーしただけのファイルなのに「一致しません」と言われる。開いて見比べても、目で追っても、差が見つからない。

目で見えないのは当たり前です。違っているのは「文字として表示されない部分」だから。原因はだいたい2つに絞れます。

⚠️ この記事の情報は2026年8月時点のものです。筆者のシステムは相場を観測・研究するためのもので、自動発注はしません(read-only)。実際のお金での発注はしていません(仮想発注のみ・実発注なし)。環境やツールの仕様は変わるため、内容は随時更新します。

この記事で分かること

結論から。「中身は同じなのに一致しない」の犯人は、ほぼ次のどちらかです。

  • BOM(ボム)=ファイルの先頭に付く、画面に表示されない印(byte order mark)
  • 改行コード=行の終わりを表す記号。WindowsのCRLFとMac/LinuxのLFで違う

どちらも「文字を1文字も書き換えていないのに、バイト列は別物になる」タイプの違いです。人間の目には同じ、機械には別物。この段差にハマると、原因を探す方向が最初から間違います。

【早見表】症状→原因→確認手順

まずここだけ見れば当たりが付きます。

症状疑うべき原因最初に見るところ
先頭の列名だけ文字化けする(1列目のヘッダーだけ変な記号が付く)ファイル先頭のBOM保存時の文字コードが「UTF-8(BOM付き)」になっていないか
1行も直していないのに差分が「全行変更」になる改行コードがCRLFとLFで食い違っているエディタ右下の改行表示(CRLF / LF)
中身は同じに見えるのにファイルサイズやハッシュ値が違う改行コードの違い、またはBOMの有無行数とバイト数の差が対応していないか
読み込みが黙って0件になる/対象から外れる先頭のBOMで解析が拒否されているエラーではなく「スキップ」扱いになっていないか
日本語を表示しようとした瞬間だけ落ちるコンソール側の文字コード(Windows日本語環境のcp932)出力先の文字コード設定

BOMとは何か

BOM(byte order mark)は、ファイルの先頭にだけ置かれる「このファイルはUTF-8です」という目印です。UTF-8では3バイト分。エディタで開いても表示されません。

厄介なのは、ソフトによって扱いが割れること。「あってもいい」と読むソフトと、「文法違反」として弾くソフトがあります。読み飛ばす側ばかり使っていると、存在に気づかないまま何年も過ごせてしまう。

BOMが付く保存操作

  • Excelで「CSV UTF-8」形式として保存したとき
  • エディタの文字コード指定を「UTF-8(BOM付き)」のまま保存したとき
  • ファイルを書き出すスクリプトが、BOM付きを既定にしているとき

「自分で付けた覚えがない」のが普通です。付けたのは保存操作のほうなので。

付いているかの確認手順

  • エディタで見る:VS Codeなら右下に文字コードが出ます。「UTF-8 with BOM」ならBOM付き。クリックでBOMなし保存に直せます。ただしBOMを外す前に、そのファイルの使い道を確認してください。ExcelでCSVを直接開く前提のファイルは、BOMを外すと日本語が文字化けすることがあります(BOMを手がかりにUTF-8と判別しているため)。BOMなしにそろえるのは、プログラムやツールで読み込む・比較するファイルに限るのが安全です
  • PowerShellで先頭バイトを覗くFormat-Hex -Path ファイル名 | Select-Object -First 1 を実行し、先頭が EF BB BF で始まっていればBOM付きです

改行コード(CRLF / LF)とは

BOMと改行コードの違いと、それぞれで出る症状を並べた比較図
図:どちらを疑うかはバイト数の差で当たりを付ける

行の終わりを表す記号にも流派があります。WindowsはCRLF(2バイト)、Mac/LinuxはLF(1バイト)。同じ文章でも、行の終わりごとに1バイトずつ差が出ます。

表示上は完全に同じ。だからこそ、差分ツールが「全行が変わりました」と言い出すと理由が分からなくなります。

中身が同じでもバイト数が変わる=自環境の実測

筆者の環境で実際に測った数字です(他の環境で同じ差になるとは限りません)。

  • ある監査記録のテキスト:LF形で10,827バイト、CRLF形で10,901バイト。差は74バイトで、これはこのファイルに含まれる74回分の改行がLFからCRLFへ変わった量とちょうど一致しました
  • ある決裁記録のJSON:LF形で2,402バイト、CRLF形で2,426バイト。差は24バイトで、24回分の改行と一致

確認手順3ステップ

バイト数の比較から原因を切り分ける3ステップの手順図
図:「一致しない」と言われたときの3ステップ

「一致しない」と言われたら、この順で見ます。

  • ステップ1:バイト数を並べる。PowerShellなら (Get-Item ファイル名).Length。2つの数字を書き出し、差が何バイトかをメモします
  • ステップ2:差の正体を当てる。差が3バイトならBOMの可能性が高い。差が行数に近い数字なら改行コードの可能性が高い。どちらでも説明が付かないときは、中身そのものの違いに加えて、行末の余分な空白・全角空白・ゼロ幅スペースといった別の見えない文字や、文字コード自体(UTF-8とShift_JISなど)の違いも疑います
  • ステップ3:エディタで裏を取る。VS Codeの右下で「文字コード」と「改行コード(CRLF / LF)」を確認し、2つのファイルで食い違っていないかを見ます

ステップ2で答えが出ることがほとんど。中身を1行ずつ見比べるのは、この3ステップで説明が付かなかったときだけで足ります。

比べる前にそろえる4手順

原因が分かったら、次は再発させない置き方です。順番が大事。

  • ①基準を先に決める。「保存はUTF-8(BOMなし)、改行はLF」のように、迷わないルールを1行で書き留める
  • ②保存側をそろえる。エディタの既定設定を変え、書き出すスクリプトの文字コード指定も明示する
  • ③比べる前に変換する。BOMを外し、改行を基準の形に直してから比較。このとき元のファイルは直接書き換えず、コピーを作ってそちらを変換する(バージョン管理下なら変換前に必ずコミットしておく)。一括変換は、まず1ファイルで結果を確かめてから広げます。この一手間を前処理として固定する
  • ④判定の入口を1か所にする。複数の経路でチェックしているなら、そろえる処理を共通化する。経路ごとに書くと片方だけ直して片方が残ります

④は地味ですが効きます。筆者も当初は片方の経路だけを直す計画でしたが、途中で気づいて両方を同じ処理に通しました。

実録:見えない1文字が4ファイルを検査から消していた2日間の時系列

ここからは筆者の記録です。題材は株の値動きを観測するために個人開発しているシステムで、相場を観測・研究するためのもの。自動発注はしません(read-only)。実際のお金での発注はしていません(仮想発注のみ・実発注なし)。

解析が拒否して黙って除外=検査は赤いのに理由が見えない

8月6日。その日のうちに追加した4つのファイルが、すべてBOM付きで保存されていました。Pythonでソースを文字列として読み込み、構文解析(ast.parse)にかける仕組みは、先頭のBOMを受け付けません。結果、リポジトリ全体を走査する仕組みはその4ファイルを「解析エラー」として記録し、検査対象から外していました

表に出ていたのは「3つのテストが赤い」という事実。ファイルを開いても中身は正しく見える。当然です、違いは表示されない先頭3バイトなのだから。

BOMを外した瞬間に別の不具合が表面化した

BOMを取り除いてファイルが検査対象に戻った途端、その下に隠れていた2つ目の問題が出てきました。2つの検査ツールが、判定結果のJSONを「日本語をそのまま出す」設定で表示していたのです。

Windows日本語環境のコンソール(cp932)では、これが文字コードのエラーになります。しかも落ち方が悪い。判定結果と終了コードを同時に失うため、合格だったのかすら残りません。

対処は、他のツールで既に使っていた安全な出力処理へ寄せること。まず日本語のまま出し、だめなら記号表記へ(情報は落ちません)、それでもだめなら生バイト列へ、と段階的に落とす形です。判定のロジックには触れていません。結果も両方とも合格のままでした。

詰まった箇所と回避策

翌8月7日、同じ根っこの問題が別の形で出ました。ファイルが差し替えられていないかを確認する照合が、作業フォルダに置かれた状態のバイト列を基準にしていたのです。

Gitには取得時に改行コードを自動変換する設定があります。同じ内容でも、取ってきた場所によってバイト列が変わる。実際、片方の作業フォルダでは合格、新しく取得し直したフォルダでは17件が不合格と、判定が反転していました。中身は一つも書き換わっていません(27件すべてで内容一致を確認)。

回避策は、比較前に「そろえる」規約を1つ決めること。UTF-8として厳密に読み、BOMを外し、CRLFと単独のCRをLFに畳んでから照合する。ポイントは2つ。

  • 照合の経路が2つあったので、両方を同じ関数に通した。片方だけ直すと、同じファイルが「どちらの経路で検査されたか」で別判定になります
  • 検出力は落とさない範囲にとどめた。吸収するのは改行の書き方とBOMの有無だけ。本文が1文字でも変われば従来どおり不一致になります。読めない形式や未知の指定は、合格に倒さず不合格にしました

同じ日、電子署名の検証でも同じことが起きていました。検証に渡す材料が作業フォルダのバイト列だったため、取得場所によって「署名が正しい/正しくない」が入れ替わる。前述の2,402/2,426バイトの実測はこのときのものです。既存の署名はLF形に対して作られていたと分かり、検証側の入り口をそろえるだけで済みました。

よくある失敗

失敗1:除外リストを広げて合格にしてしまう

「このファイルだけ検査から外せば全部緑になる」。一番手が伸びやすく、一番危ない選択肢です。緑になった画面は、問題が消えた証拠ではなく見なくなった証拠でしかない。筆者の場合、外したのは除外リストではなくBOMによる自動スキップでしたが、結果は同じでした。検査から外れていた4ファイルの下に不具合が2つ眠っていました。

失敗2:エラーが出ないから正常だと判断する

BOMがらみの一番いやらしい点はここ。派手に落ちてくれず、「読み込みました、0件でした」と静かに返ってきます。件数がゼロ・対象が空は「異常なし」ではなく「何かがおかしい」のサインとして扱うほうが安全。件数を毎回確認する習慣のほうが、エラーを待つより早く気づけます。

非エンジニアが得た教訓

  • 「同じに見える」は「同じ」ではない。表示されない部分にこそ差が入る。目視は証拠にならない
  • 黙って外されるものが一番危ない。赤いエラーより、静かなスキップのほうが長く生き残る
  • 直したら次が出るのは正常。1つ目を取り除いたから2つ目が見えた。前進の合図です
  • そろえてから比べる。比較の前処理を決めておけば、同じ迷子を繰り返さずに済みます

まとめと次に読む

中身が同じなのに一致しないとき、まずバイト数の差を見る。3バイトならBOM、行数分なら改行コードのことが多い。そのどちらでも説明が付かなければ、中身や他の不可視文字を疑う。

ただし、BOMを外せばどんな不一致も解消するわけではありません。筆者の環境でも、外した先にまた別の問題が出てきました。ここで書いたのは自分の環境での記録と、そこから作った確認の順番です。同じ症状でも原因は環境によって変わります。

それでも「見えないものを疑う」発想を一度持てたかどうかで、次の時間の使い方は変わります。CSVを扱う場面が多い方は、マーケットスピード2 RSSの使い方のようなデータ取り込み作業でも同じ落とし穴が待っています。


関連記事

無料テンプレート配布のお知らせ

非エンジニアの自動化ラボ メルマガ 読者登録フォーム

Claude Codeを安全・便利に使うための設定テンプレート(CLAUDE.md)を無料配布しています。メールアドレスをご登録いただくと、すぐにダウンロードリンクをお送りします。


免責事項

本記事は執筆時点(2026年8月)の情報に基づく、筆者個人の体験の記録です。記事中の自動売買システムに関する記述は、特定の投資手法や自動売買の利用を推奨するものではありません。投資には元本割れのリスクがあり、最終的な判断はご自身の責任で行ってください。また、本記事ではセキュリティに関わる話題に触れていますが、悪用防止の観点から、具体的な脆弱性や攻撃手法の詳細は記載していません。AIツールの仕様は予告なく変更される場合があります。最新情報は各公式ドキュメントをご確認ください。本記事の内容を用いて生じたいかなる損害についても、筆者は責任を負いかねます。

コメント

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