Windows の文字コードと改行コードを整理する - Shift_JIS / UTF-8 / UTF-16、文字化け、CRLF / LF、なぜ混乱するのか
Windows のテキストまわりの相談では、かなりの頻度で次の話が一気に混ざります。
Shift_JISとUTF-8は何が違うのか- なぜ文字化けが起きるのか
CRLFとLFは何が違うのかUTF-8にしたのに、なぜ読めないことがあるのか- なぜ同じ file なのに editor、console、Excel、Git で見え方が変わるのか
この話は、日本語が難しいから起きるわけではありません。ほとんどは、同じバイト列を別の前提で読んだ か、読み間違えた内容をそのまま保存した ことが原因です。
さらに Windows では、Unicode の世界と code page の世界が今も共存しています。そこへ BOM、改行コード、editor の自動判定、console の code page、Git の改行変換まで重なるので、話がややこしく見えます。
この記事では、Windows でよく混ざる Shift_JIS / UTF-8 / UTF-16、なぜ文字化けが起きるのか、CRLF と LF の違い、そしてなぜこの話が混乱しやすいのかを、実務向けに整理します。
内容は 2026 年 4 月時点の Microsoft Learn、PowerShell、Git、W3C / Unicode 系の公開情報を前提にしています。詳細は末尾の参考資料を参照してください。
目次
- まず押さえたいこと
- 用語を分解する
- 2.1 Unicode / UTF-8 / UTF-16 / CP932 は何が違うのか
- 2.2
Shift_JISとCP932をどう考えるか - 2.3
ANSI、Unicode、UTF-8Nという言葉の罠
- なぜ文字化けが起きるのか
- 3.1 文字化けの正体
- 3.2 表示崩れとデータ破損は別
- 3.3 表現できない文字へ落とすと戻らない
- 改行文字の違いとは
- 4.1
CRLF/LF/CR - 4.2 改行は文字コードとは別問題
- 4.3
\nと file 上の改行 bytes は同じとは限らない
- 4.1
- なぜ Windows では特に混乱しやすいのか
- 5.1 Unicode と legacy code page が共存している
- 5.2 ラベルが揃っていない
- 5.3 ASCII だけだと問題が隠れる
- 5.4 file 内容、file 名、console、source file は別レイヤ
- 5.5 BOM と改行コードも別軸で効く
- 5.6 ツールが勝手に変える
- よくある事故パターン
- 実務で事故を減らすルール
- 文字化け・行末差分の調査はこの 5 問で進める
- まとめ
- 関連記事
- 参考資料
1. まず押さえたいこと
先に結論だけ並べると、重要なのは次の 7 点です。
- text file は、文字列そのもの ではなく、bytes + 文字コード + 改行コード で成り立っています。場合によっては BOM も付きます。
- 文字化けは、同じ bytes を別の文字コードとして decode した ときに起きます。
- 改行トラブルは、文字コードが正しくても行区切りの前提がずれている ときに起きます。
UnicodeとUTF-8は同じ意味ではありません。Unicodeは文字集合側の話で、UTF-8やUTF-16は encoding の話です。- Windows で「
Shift_JIS」と呼ばれているものは、実務では CP932 / Windows 系の日本語 code page と意識したほうが会話がぶれにくいです。 UTF-8 にしただけでは、まだ仕様として足りません。BOM の有無 と 改行コード まで決めて初めて運用ルールになります。- 混乱の元は、日本語そのもの ではなく、歴史の違う複数の前提が同じ Windows 上に残っていること です。
要するに、Windows の text を扱うときは、次の 4 つを分けて考えるのが出発点です。
- その file の bytes は何か
- どの encoding で書かれたか
- どの encoding で読まれたか
- 改行は
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_JIS と CP932 をどう考えるか
現場では、日本語 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ではなくCP932ANSIではなくACP (active code page) / 日本語環境では通常 CP932textではなくUTF-8 no BOM, LFのように具体化する
2.3 ANSI、Unicode、UTF-8N という言葉の罠
Windows まわりでは、言葉のラベルも混乱の原因です。
特に多いのは次です。
ANSI
Windows の UI や古い説明で出てきますが、ASCII ではありません。多くの場合は そのマシンの active code page を指します。Unicode
一部の editor やツールでは、menu 上のUnicodeが UTF-16LE を意味することがあります。Unicode で保存したと言われてもUTF-8とは限りません。UTF-8N
日本語圏の editor で見かけることがありますが、これはふつう UTF-8 no BOM を区別するための UI ラベルです。encoding の正式名称ではありません。
つまり、同じ言葉でもツールごとに意味がずれる のが Windows です。ここが、最初の大きな混乱ポイントです。
3. なぜ文字化けが起きるのか
3.1 文字化けの正体
文字化けの正体は、かなり単純です。
- 文字列を、ある encoding で bytes にする
- その bytes を、別の encoding で文字列へ戻す
- 前提が一致していなければ、別の文字列になる
たとえば あ を UTF-8 で保存すると、bytes は次です。
E3 81 82
これを UTF-8 として読めば あ ですが、CP932 側の前提で読めば 縺� のような別の文字列に見えます。
このとき壊れているのは「日本語」ではなく、decode の前提 です。
文字化けを 1 行で言うなら、こうです。
同じ bytes を、違う encoding として読んだ。
3.2 表示崩れとデータ破損は別
ここで大事なのは、まだ戻せる段階 と もう戻しにくい段階 を分けることです。
たとえば次の流れなら、まだ戻せる可能性があります。
- UTF-8 の file を CP932 として開く
- 画面上では
縺�のように見える - まだ保存していない
この段階では、元の bytes は UTF-8 のまま残っています。正しい encoding で開き直せば戻ることがあります。
危ないのは次です。
- UTF-8 の file を CP932 として誤読する
- 壊れて見えている内容を、そのまま保存する
- もとの UTF-8 bytes が失われる
ここまで行くと、表示崩れではなくデータ破損 です。
実務では、「文字化けした」という 1 文でまとめずに、少なくとも次を分けるのが大事です。
- bytes 自体はまだ正しいのか
- 誤読した内容がすでに再保存されたのか
3.3 表現できない文字へ落とすと戻らない
もう 1 つ危ないのは、Unicode 文字列を CP932 のような狭い code page に落とすときです。
このとき、相手側に存在しない文字が含まれていると、次のどれかが起きます。
?に置き換わる- 置換文字が入る
- 変換エラーになる
- 別の近い文字へ寄せられる
たとえば、一部の絵文字や拡張漢字は CP932 へそのまま落とせません。
この事故は「読めるかどうか」ではなく、往復変換して元に戻るか で考えるべきです。
一度失われた情報は、あとから正しい encoding を知っても元に戻りません。
4. 改行文字の違いとは
4.1 CRLF / LF / CR
改行も bytes です。
CR= carriage return =0DLF= 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なのに改行はLFUTF-16LEなのに改行はCRLF
は普通にありえます。
なので、UTF-8 にしたのにまだ違う というとき、実際には encoding ではなく改行だけがずれている ことがあります。
4.3 \n と file 上の改行 bytes は同じとは限らない
プログラマ視点で地味に混乱しやすいのがここです。
source code の中で \n と書いたからといって、file 上に必ず 0A だけが出るとは限りません。
言語やランタイム、I/O API の text mode では、Windows 上で \n が CRLF に変換されることがあります。
つまり、次がずれる可能性があります。
- ソースコード上の改行表現
- 実行時の文字列
- 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と言っているが、実態は CP932ANSIと言っているが、実態は active code pageUnicodeと言っているが、実態は UTF-16LEUTF-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 はあるか、ないか
- 改行は
CRLFかLFか
たとえば、同じ 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 BOMかUTF-8 no BOMか- 改行は
CRLFかLFか - 誰が読む file なのか
- legacy Windows ツール互換が必要か
- Linux / macOS / CI / container も読むのか
たとえば、cross-platform 前提の source code や config なら、UTF-8 no BOM + LF が第一候補になりやすいです。
一方で、Windows の古いツールや既存運用へ合わせる必要があるなら、UTF-8 with BOM や CP932 + 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 問に戻るのが一番早いです。
- 今この file の bytes は何か
- UTF-8 か
- UTF-8 with BOM か
- CP932 か
- UTF-16LE か
- 最初に誰が、どの前提で書いたか
- editor
- legacy app
- Excel export
- shell / script
- batch / middleware
- 今誰が、どの前提で読んでいるか
- editor の auto-detect
- console の code page
- library の default encoding
- import 側の仕様
- BOM と改行は何か
- BOM あり / なし
CRLF/LF
- 誤読した内容が、すでに保存されたか
- まだ表示だけか
- すでに再保存されて bytes が失われたか
この 5 問が埋まると、たいてい原因は見えてきます。
9. まとめ
Windows の文字コードと改行コードがややこしく見えるのは、日本語そのものが難しいからではありません。
bytes、encoding、BOM、newline、tool の既定値 が別々に存在し、そのうえで Windows には新旧の text 文化が同居しているからです。
特に覚えておきたいのは次です。
- 文字化けは、同じ bytes を別の encoding として読んだ結果
- 改行問題は、encoding とは別軸の話
Shift_JIS、CP932、ANSI、Unicodeという言葉はそのまま信用しすぎないUTF-8 にしただけでは不十分で、BOM と改行も必要- 表示崩れと、再保存済みのデータ破損は分けて考える
- 仕様では
textではなくUTF-8 no BOM, LFのように書く
要するに、Windows の text を扱うときは「文字列の話」ではなく、bytes の約束をどう揃えるか の話だと考えるのが実務的です。
10. 関連記事
- Windows の文字コードを整理する - なぜ文字化けが起きるのか、特に Linux と組み合わせたときに何がずれるのか
- Windows 環境で Codex の文字化け事故を減らすベストプラクティス - 環境整備より『こう指示する』を先に決める
11. 参考資料
- Microsoft Learn, Code Page Identifiers - Win32 apps
https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers - 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 - 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 - W3C Internationalization, Character encodings: Essential concepts
https://www.w3.org/International/articles/definitions-characters/ - Git documentation, gitattributes
https://git-scm.com/docs/gitattributes - Git documentation, git-config
https://git-scm.com/docs/git-config
関連する記事
同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。
Windows の文字コードを整理する - なぜ文字化けが起きるのか、特に Linux と組み合わせたときに何がずれるのか
Windows の文字コードを、なぜ文字化けが起きるのかという観点で整理します。CP932、UTF-8、UTF-16、BOM、console の code page、PowerShell、Linux の locale まで、実務で事故が増えやすいポイントをまとめます。
Windows 環境で Codex の文字化け事故を減らすベストプラクティス - 環境整備より『こう指示する』を先に決める
Windows で Codex に日本語ファイルを扱わせるとき、推測保存を避け、既存 encoding を維持し、再読込で検証するための実務的な指示ルールを整理します。
ClickOnce とは何か - 仕組み、更新、向いている場面・向いていない場面を実務目線で整理
.NET の Windows デスクトップアプリ配布で使われる ClickOnce について、マニフェスト、更新、キャッシュ、署名、向いている案件・向いていない案件を Mermaid 図つきで整理します。
Windows サンドボックスで Windows アプリ開発の検証を速くする方法 - 管理者権限問題、クリーン環境、権限不足・リソース不足の再現を実務向けに整理
Windows Sandbox を使って、管理者権限の問題の切り分け、クリーン環境での再現、権限不足・リソース不足の再現を効率化する方法を、.wsb と CLI の使い分けまで含めて整理します。
Windows での DLL の名前解決の仕組み - 検索順序、Known DLLs、API set、SxS を実務向けに整理
Windows の DLL 名前解決を、DLL search order、Known DLLs、loaded-module list、API set、SxS manifest、LoadLibrary 系 API の影響まで実務向けに整理します。
関連トピック
このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。
Windows技術トピック
Windows 開発、不具合調査、既存資産活用の技術トピックをまとめた入口です。
このテーマがつながるサービス
この記事は次のサービスページにつながります。近い入口からご覧ください。
技術相談・設計レビュー
Windows と Linux の間で CSV、ログ、設定ファイルの文字コード前提がずれる案件では、I/O 契約と運用ルールを先に整理すると事故を減らしやすいです。
Windowsアプリ開発
Windows 向け業務ツールでは、CP932 と UTF-8 が混在する現場が多く、文字コードと改行コードの扱いを設計に入れておくことが保守性に直結します。