Windows の文字コードと改行コードを整理する - Shift_JIS / UTF-8 / UTF-16、文字化け、CRLF / LF、なぜ混乱するのか

· · Windows, 文字コード, 文字化け, 改行コード, UTF-8, CP932, PowerShell, Unicode

Windows のテキストまわりの相談では、かなりの頻度で次の話が一気に混ざります。

  • Shift_JISUTF-8 は何が違うのか
  • なぜ文字化けが起きるのか
  • CRLFLF は何が違うのか
  • UTF-8 にしたのに、なぜ読めないことがあるのか
  • なぜ同じ file なのに editor、console、Excel、Git で見え方が変わるのか

この話は、日本語が難しいから起きるわけではありません。ほとんどは、同じバイト列を別の前提で読んだ か、読み間違えた内容をそのまま保存した ことが原因です。

さらに Windows では、Unicode の世界と code page の世界が今も共存しています。そこへ BOM、改行コード、editor の自動判定、console の code page、Git の改行変換まで重なるので、話がややこしく見えます。

この記事では、Windows でよく混ざる Shift_JIS / UTF-8 / UTF-16、なぜ文字化けが起きるのか、CRLFLF の違い、そしてなぜこの話が混乱しやすいのかを、実務向けに整理します。

内容は 2026 年 4 月時点の Microsoft Learn、PowerShell、Git、W3C / Unicode 系の公開情報を前提にしています。詳細は末尾の参考資料を参照してください。

目次

  1. まず押さえたいこと
  2. 用語を分解する
    • 2.1 Unicode / UTF-8 / UTF-16 / CP932 は何が違うのか
    • 2.2 Shift_JISCP932 をどう考えるか
    • 2.3 ANSIUnicodeUTF-8N という言葉の罠
  3. なぜ文字化けが起きるのか
    • 3.1 文字化けの正体
    • 3.2 表示崩れとデータ破損は別
    • 3.3 表現できない文字へ落とすと戻らない
  4. 改行文字の違いとは
    • 4.1 CRLF / LF / CR
    • 4.2 改行は文字コードとは別問題
    • 4.3 \n と file 上の改行 bytes は同じとは限らない
  5. なぜ Windows では特に混乱しやすいのか
    • 5.1 Unicode と legacy code page が共存している
    • 5.2 ラベルが揃っていない
    • 5.3 ASCII だけだと問題が隠れる
    • 5.4 file 内容、file 名、console、source file は別レイヤ
    • 5.5 BOM と改行コードも別軸で効く
    • 5.6 ツールが勝手に変える
  6. よくある事故パターン
  7. 実務で事故を減らすルール
  8. 文字化け・行末差分の調査はこの 5 問で進める
  9. まとめ
  10. 関連記事
  11. 参考資料

1. まず押さえたいこと

先に結論だけ並べると、重要なのは次の 7 点です。

  • text file は、文字列そのもの ではなく、bytes + 文字コード + 改行コード で成り立っています。場合によっては BOM も付きます。
  • 文字化けは、同じ bytes を別の文字コードとして decode した ときに起きます。
  • 改行トラブルは、文字コードが正しくても行区切りの前提がずれている ときに起きます。
  • UnicodeUTF-8 は同じ意味ではありません。Unicode は文字集合側の話で、UTF-8UTF-16 は encoding の話です。
  • Windows で「Shift_JIS」と呼ばれているものは、実務では CP932 / Windows 系の日本語 code page と意識したほうが会話がぶれにくいです。
  • UTF-8 にした だけでは、まだ仕様として足りません。BOM の有無改行コード まで決めて初めて運用ルールになります。
  • 混乱の元は、日本語そのもの ではなく、歴史の違う複数の前提が同じ Windows 上に残っていること です。

要するに、Windows の text を扱うときは、次の 4 つを分けて考えるのが出発点です。

  1. その file の bytes は何か
  2. どの encoding で書かれたか
  3. どの encoding で読まれたか
  4. 改行は CRLF / LF のどちらか

ここが分かれるだけで、かなり迷いにくくなります。

2. 用語を分解する

2.1 Unicode / UTF-8 / UTF-16 / CP932 は何が違うのか

まず、言葉を 1 回分解したほうが早いです。

用語 何を指すか よくある混同
Unicode 文字を番号で表すための枠組み U+3042 () UTF-8 と同じものだと思う
UTF-8 Unicode を bytes にする encoding E3 81 82 Unicode 自体だと思う
UTF-16LE Unicode を bytes にする encoding 42 30 menu 上の Unicode 表記と混ざる
CP932 Windows 日本語系の legacy code page 82 A0 Shift_JIS と完全に同じだと思う
CRLF / LF 行の区切り bytes 0D 0A / 0A encoding の一種だと思う
BOM file 先頭の識別用 bytes EF BB BF など encoding 名そのものだと思う

たとえば という 1 文字でも、bytes は encoding ごとに違います。

文字: あ

UTF-8    : E3 81 82
CP932    : 82 A0
UTF-16LE : 42 30

大事なのは、文字と bytes は別物 だということです。アプリは画面上では「文字」に見えるものを扱っていますが、保存や通信では最終的に bytes をやり取りします。事故はだいたい、その変換の境界で起きます。

2.2 Shift_JISCP932 をどう考えるか

現場では、日本語 Windows の text file をまとめて「Shift_JIS」と呼ぶことがかなり多いです。会話としては通じますが、実務では少し雑です。

Windows の日本語 legacy text を正確寄りに意識するなら、CP932、あるいは Windows 系の日本語 code page と考えたほうが安全です。

ここを雑にすると、次のような会話がぶれます。

  • Shift_JIS で保存して と言ったが、相手は Windows 側の CP932 を想定していた
  • Linux / macOS 側では shift_jis として扱ったが、Windows 由来 file の一部で再現が合わない
  • ANSI 保存と言われたが、何の code page かは環境依存だった

なので、仕様や調査メモでは、できるだけ次のように書くほうが安全です。

  • Shift_JIS ではなく CP932
  • ANSI ではなく ACP (active code page) / 日本語環境では通常 CP932
  • text ではなく UTF-8 no BOM, LF のように具体化する

2.3 ANSIUnicodeUTF-8N という言葉の罠

Windows まわりでは、言葉のラベルも混乱の原因です。

特に多いのは次です。

  • ANSI
    Windows の UI や古い説明で出てきますが、ASCII ではありません。多くの場合は そのマシンの active code page を指します。
  • Unicode
    一部の editor やツールでは、menu 上の UnicodeUTF-16LE を意味することがあります。Unicode で保存した と言われても UTF-8 とは限りません。
  • UTF-8N
    日本語圏の editor で見かけることがありますが、これはふつう UTF-8 no BOM を区別するための UI ラベルです。encoding の正式名称ではありません。

つまり、同じ言葉でもツールごとに意味がずれる のが Windows です。ここが、最初の大きな混乱ポイントです。

3. なぜ文字化けが起きるのか

3.1 文字化けの正体

文字化けの正体は、かなり単純です。

  1. 文字列を、ある encoding で bytes にする
  2. その bytes を、別の encoding で文字列へ戻す
  3. 前提が一致していなければ、別の文字列になる

たとえば を UTF-8 で保存すると、bytes は次です。

E3 81 82

これを UTF-8 として読めば ですが、CP932 側の前提で読めば 縺� のような別の文字列に見えます。
このとき壊れているのは「日本語」ではなく、decode の前提 です。

文字化けを 1 行で言うなら、こうです。

同じ bytes を、違う encoding として読んだ。

3.2 表示崩れとデータ破損は別

ここで大事なのは、まだ戻せる段階もう戻しにくい段階 を分けることです。

たとえば次の流れなら、まだ戻せる可能性があります。

  1. UTF-8 の file を CP932 として開く
  2. 画面上では 縺� のように見える
  3. まだ保存していない

この段階では、元の bytes は UTF-8 のまま残っています。正しい encoding で開き直せば戻ることがあります。

危ないのは次です。

  1. UTF-8 の file を CP932 として誤読する
  2. 壊れて見えている内容を、そのまま保存する
  3. もとの UTF-8 bytes が失われる

ここまで行くと、表示崩れではなくデータ破損 です。

実務では、「文字化けした」という 1 文でまとめずに、少なくとも次を分けるのが大事です。

  • bytes 自体はまだ正しいのか
  • 誤読した内容がすでに再保存されたのか

3.3 表現できない文字へ落とすと戻らない

もう 1 つ危ないのは、Unicode 文字列を CP932 のような狭い code page に落とすときです。

このとき、相手側に存在しない文字が含まれていると、次のどれかが起きます。

  • ? に置き換わる
  • 置換文字が入る
  • 変換エラーになる
  • 別の近い文字へ寄せられる

たとえば、一部の絵文字や拡張漢字は CP932 へそのまま落とせません。
この事故は「読めるかどうか」ではなく、往復変換して元に戻るか で考えるべきです。

一度失われた情報は、あとから正しい encoding を知っても元に戻りません。

4. 改行文字の違いとは

4.1 CRLF / LF / CR

改行も bytes です。

  • CR = carriage return = 0D
  • LF = line feed = 0A
  • Windows の text file では CRLF (0D 0A) が伝統的
  • Linux / Unix 系では LF (0A) が一般的
  • CR 単独は旧 Mac 系などの古い文脈で出ることがある

表にするとこうです。

改行 bytes 主な文脈
CRLF 0D 0A Windows の従来 text file、legacy ツール
LF 0A Linux / macOS / 多くの開発ツール
CR 0D かなり古い legacy data

4.2 改行は文字コードとは別問題

ここがかなり重要です。

改行コードは encoding とは別問題 です。

同じ UTF-8 の file でも、改行は CRLF にも LF にもなります。
たとえば A、改行、B という内容なら bytes は次のように変わります。

UTF-8 + LF   : 41 0A 42
UTF-8 + CRLF : 41 0D 0A 42

つまり、

  • UTF-8 なのに改行だけ違う
  • CP932 なのに改行は LF
  • UTF-16LE なのに改行は CRLF

は普通にありえます。

なので、UTF-8 にしたのにまだ違う というとき、実際には encoding ではなく改行だけがずれている ことがあります。

4.3 \n と file 上の改行 bytes は同じとは限らない

プログラマ視点で地味に混乱しやすいのがここです。

source code の中で \n と書いたからといって、file 上に必ず 0A だけが出るとは限りません。
言語やランタイム、I/O API の text mode では、Windows 上で \nCRLF に変換されることがあります。

つまり、次がずれる可能性があります。

  • ソースコード上の改行表現
  • 実行時の文字列
  • file に保存された bytes
  • editor 上で見える改行

このため、「自分は LF を書いたつもりだったのに file は CRLF だった」という事故が起きます。

最近の editor は LF 単独を普通に扱えますが、周辺ツール、legacy アプリ、業務運用はまだ CRLF 前提が残っています。
そのため、改行問題は「昔の話」ではなく、今も実務で普通に出ます。

5. なぜ Windows では特に混乱しやすいのか

5.1 Unicode と legacy code page が共存している

Windows がややこしい最大の理由はこれです。

Windows には、

  • Unicode を使う道
  • code page ベースで扱う道

の両方が残っています。

新しめのアプリ、web、cross-platform 系の資産は UTF-8 へ寄りやすい一方で、古い CSV、TXT、ログ、Excel 周辺、業務システム連携では CP932 が残っています。
さらに、一部の出力や API 周辺では UTF-16LE も普通に出ます。

つまり、1 台の Windows の中に複数の text 文化が同居している のです。

5.2 ラベルが揃っていない

混乱を増やすのは、技術そのものよりもラベルのずれです。

  • Shift_JIS と言っているが、実態は CP932
  • ANSI と言っているが、実態は active code page
  • Unicode と言っているが、実態は UTF-16LE
  • UTF-8 と言っているが、実際には BOM あり / なしが未確定
  • UTF-8N のような editor 独自ラベルが出てくる

ここを曖昧にすると、会話では通じているように見えて、実体が揃っていません。

5.3 ASCII だけだと問題が隠れる

これも大きいです。

UTF-8 は ASCII 範囲と互換性があるため、英数字と記号だけの file は、間違った前提でも「何となく読めてしまう」ことがあります。
CP932 側でも ASCII 相当の範囲は見た目が壊れにくいので、問題が表面化しません。

その結果、次のような状態になります。

  • 英語だけの config は問題なく見える
  • 日本語を 1 行入れた瞬間に壊れる
  • ずっと潜んでいた問題が、運用中に初めて発火する

だから文字コード事故は、「昨日まで動いていたのに、今日から急に壊れた」ように見えやすいです。
実際には、前から地雷はあって、非 ASCII 文字が入った瞬間に見えただけ ということが多いです。

5.4 file 内容、file 名、console、source file は別レイヤ

Windows では、次をまとめて「文字コード」と呼ぶと迷います。

  • file 名 / path
  • file の中身
  • console への表示
  • source code file 自体の encoding
  • 実行時の文字列形式
  • clipboard や GUI 部品上の表示

たとえば、日本語の file 名が普通に見えていても、file の中身は CP932 で保存されているかもしれません。
逆に file 自体は UTF-8 でも、console の code page が合っていなければ表示だけ壊れます。

chcp 65001 のような操作も、基本的には console 側の前提に効く話であって、既存 file の bytes を変える話ではありません。

さらに、source code file が UTF-8 でも、実行時に書き出す log file が UTF-8 とは限りません。
どの層の encoding の話をしているか を毎回分ける必要があります。

なお、日本語 Windows では \ が円記号に見えることがあり、これも文字コードの話と混ざりやすいです。
ただし多くの場合、これは 表示フォントや glyph の問題 であって、path 区切りやエスケープの意味が変わったわけではありません。

5.5 BOM と改行コードも別軸で効く

UTF-8 という言い方だけでは、まだ半分しか決まっていません。

実務では、次も効きます。

  • BOM はあるか、ないか
  • 改行は CRLFLF

たとえば、同じ UTF-8 でも、

  • BOM ありなら読める Windows ツールがある
  • BOM があると先頭列に余計な文字が乗る Unix 系処理がある
  • LF だけだと legacy 側で扱いにくいツールがある
  • CRLF だと shell script や diff が荒れることがある

という具合に、encoding が合っていてもまだ事故る のです。

5.6 ツールが勝手に変える

さらに厄介なのが、手元のツールが暗黙に変えることです。

  • editor が auto-detect する
  • save 時に BOM を付ける / 外す
  • Git が CRLF / LF を変換する
  • shell や command が既定の encoding で保存する
  • CSV export が想定外の code page を使う
  • 別 version の PowerShell や tool で既定値が違う

つまり、作業者が明示していなくても、どこかの層が勝手に前提を足してくる のが Windows 実務です。

これが「自分は何も変えていないのに壊れた」の正体です。
実際には、人ではなく ツールの既定値 が変えていることが少なくありません。

6. よくある事故パターン

典型事故を表にすると、次のようになります。

場面 実際にずれているもの 典型症状
UTF-8 no BOM の設定 file を legacy Windows tool が ANSI / CP932 とみなす decode 前提 日本語だけ文字化けする
CP932 の CSV を UTF-8 前提の処理系へ渡す decode 前提 、decode error、意味不明な日本語
UTF-16LE の log を Unix 系 text tool へ渡す encoding 前提 NUL byte が混ざり、バイナリっぽく見える
LF の source file を別環境で CRLF へ変換する 改行前提 巨大な行末差分、script の不具合
誤読した内容をそのまま保存する bytes 自体が別物になる 元に戻せないデータ破損
CSV を出して とだけ仕様を書く interface が未定義 Excel では読めるが別ツールでは壊れる
UTF-8 に統一 とだけ決める BOM / 改行が未定義 一部の tool だけ失敗する

特に危ないのは、表示崩れを見たあと、そのまま保存して事故を確定させる パターンです。

7. 実務で事故を減らすルール

ここからは、運用ルールとして何を決めると事故が減るかです。

7.1 新規 text の基本線を決める

新規 file では、まず UTF-8 を第一候補にするのが妥当です。
ただし、それだけでは足りません。

最低限、次まで決めたほうが安全です。

  • UTF-8 with BOMUTF-8 no BOM
  • 改行は CRLFLF
  • 誰が読む file なのか
  • legacy Windows ツール互換が必要か
  • Linux / macOS / CI / container も読むのか

たとえば、cross-platform 前提の source code や config なら、UTF-8 no BOM + LF が第一候補になりやすいです。
一方で、Windows の古いツールや既存運用へ合わせる必要があるなら、UTF-8 with BOMCP932 + CRLF がまだ必要なこともあります。

重要なのは、「何が正しいか」の一般論より、誰とやり取りするか で決めることです。

7.2 既存 legacy file は勝手に変えない

既存の file が CP932 なら、日常の小修正のついでに UTF-8 化しないほうが安全です。

安全なのは次の運用です。

  • 既存 file は、元の encoding / BOM / 改行を維持する
  • encoding 変換は、別の移行タスクとして分ける
  • 変換対象と下流 consumer を確認してから一括変換する

文字化け事故は、善意の「ついでに modern 化」で起きることがかなり多いです。

7.3 encoding と改行を interface の一部として扱う

CSV、TXT、log、設定 file、簡易 protocol は、内容だけでなく text 形式自体が interface です。

仕様には、最低でも次を書いたほうが安全です。

  • encoding
  • BOM の有無
  • newline style
  • header の有無
  • quote / delimiter の仕様
  • どのツールで検証したか

たとえば CSV という 3 文字だけでは不十分です。
UTF-8 with BOM, CRLF, comma delimiter, header あり まで書いて初めて、会話がずれにくくなります。

7.4 読み書きの境界では明示する

コード側でも、暗黙の既定値に寄せないほうが安全です。

  • file read / write 時は encoding を明示する
  • process 間の text 受け渡しでも encoding を意識する
  • export / import 処理では改行も仕様として固定する
  • shell の雑な redirect を本番経路にしない

特に Windows では、「保存できた」ことと「正しい bytes で保存できた」ことは同じではありません。

7.5 Git と editor のルールも共有する

Git は encoding を自動で正してくれる道具ではありません。
一方で、line endings については変換が入ることがあります。

なので、repository 単位で次を決めたほうが安全です。

  • source code は LF を基本にするか
  • Windows 専用 text は CRLF を許容するか
  • .gitattributes でどう固定するか
  • editor 設定をどう共有するか

encoding と line endings を別々に考えることが重要です。
Git が改行をそろえてくれても、encoding 事故はそのまま残ります。

7.6 「文字化けした」で止まらず、何がずれたか言う

現場では、次の言い換えがかなり効きます。

  • 悪い言い方: 文字化けしました
  • 良い言い方: UTF-8 no BOM の file を CP932 前提で開いているように見えます
  • 悪い言い方: 行末がおかしいです
  • 良い言い方: LF の file が CRLF へ変換されて差分が増えています

何がずれたかが言えるだけで、調査速度はかなり変わります。

8. 文字化け・行末差分の調査はこの 5 問で進める

調査で迷ったら、次の 5 問に戻るのが一番早いです。

  1. 今この file の bytes は何か
    • UTF-8 か
    • UTF-8 with BOM か
    • CP932 か
    • UTF-16LE か
  2. 最初に誰が、どの前提で書いたか
    • editor
    • legacy app
    • Excel export
    • shell / script
    • batch / middleware
  3. 今誰が、どの前提で読んでいるか
    • editor の auto-detect
    • console の code page
    • library の default encoding
    • import 側の仕様
  4. BOM と改行は何か
    • BOM あり / なし
    • CRLF / LF
  5. 誤読した内容が、すでに保存されたか
    • まだ表示だけか
    • すでに再保存されて bytes が失われたか

この 5 問が埋まると、たいてい原因は見えてきます。

9. まとめ

Windows の文字コードと改行コードがややこしく見えるのは、日本語そのものが難しいからではありません。
bytes、encoding、BOM、newline、tool の既定値 が別々に存在し、そのうえで Windows には新旧の text 文化が同居しているからです。

特に覚えておきたいのは次です。

  • 文字化けは、同じ bytes を別の encoding として読んだ結果
  • 改行問題は、encoding とは別軸の話
  • Shift_JISCP932ANSIUnicode という言葉はそのまま信用しすぎない
  • UTF-8 にした だけでは不十分で、BOM と改行も必要
  • 表示崩れと、再保存済みのデータ破損は分けて考える
  • 仕様では text ではなく UTF-8 no BOM, LF のように書く

要するに、Windows の text を扱うときは「文字列の話」ではなく、bytes の約束をどう揃えるか の話だと考えるのが実務的です。

10. 関連記事

11. 参考資料

  1. Microsoft Learn, Code Page Identifiers - Win32 apps
    https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
  2. Microsoft Learn, about_Character_Encoding - PowerShell
    https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding?view=powershell-7.6
  3. Microsoft Learn, Understanding file encoding in VS Code and PowerShell
    https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/vscode/understanding-file-encoding?view=powershell-7.6
  4. W3C Internationalization, Character encodings: Essential concepts
    https://www.w3.org/International/articles/definitions-characters/
  5. Git documentation, gitattributes
    https://git-scm.com/docs/gitattributes
  6. Git documentation, git-config
    https://git-scm.com/docs/git-config

関連する記事

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

関連トピック

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

このテーマがつながるサービス

この記事は次のサービスページにつながります。近い入口からご覧ください。

ブログ一覧に戻る