Windowsコンソールの文字エンコーディング対応状況を検証する
はじめに
Windowsには複数のコンソール環境が存在し、それぞれ文字エンコーディングの扱いが異なります。特に日本語環境では、Shift_JIS(cp932)、UTF-8、UTF-16 など複数のエンコーディングが混在するため、ファイルの読み書き時に文字化けが発生するケースが少なくありません。
本記事では、以下の3つのコンソール環境について、各種文字エンコーディングのファイルを正しく読み書きできるかを検証しました。
- コマンドプロンプト(cmd.exe)
- Windows PowerShell 5.1
- PowerShell 7.5.4
検証は「デフォルト設定でのファイル読み込み・リダイレクト」と「エンコーディングを明示的に指定した場合の出力」の2つの観点で行っています。
検証環境
| 項目 | バージョン |
|---|---|
| OS | Windows 11 25H2 |
| コマンドプロンプト | cmd.exe(cp932) |
| Windows PowerShell | 5.1 |
| PowerShell | 7.5.4 |
テストデータ
ASCII文字・カタカナ・漢字を含む複数行の日本語テキストファイル(text1.txt)を使用しました。
TESTストリングaaa日本語国債発行
TESTストリングbbb日本語
...(以下、同様の形式で計18行)
このテストファイルを13種類の文字エンコーディングで用意し、それぞれの読み込み・出力結果を確認しています。
検証1:デフォルト設定でのファイル読み込みとリダイレクト
各コンソールのデフォルト設定で、異なるエンコーディングのテキストファイルをリダイレクトし、出力ファイルが正しく読めるかを検証しました。
検証コマンド
cmd.exe:
type text1.txt > workc.txt
Windows PowerShell 5.1 / PowerShell 7.5.4:
Get-Content -Path "text1.txt" > work.txt
Get-Content -Path "text1.txt" | Set-Content set.txt
Get-Content -Path "text1.txt" | Out-File out.txt
PowerShell では >(Out-File 相当)と Set-Content で出力エンコーディングの挙動が異なるため、両方を検証しています。
結果サマリー
リダイレクトや出力結果の表示は以下の様です。
- ✅ 可能: 日本語テキストが正常に表示される
- ❌ 不可: 文字化け、表示エラー
cmd.exe(chcp 932)
| エンコーディング | 結果 | 備考 |
|---|---|---|
| Shift_JIS | ✅ | |
| UTF-8 | ✅ | |
| UTF-8(BOM付き) | ✅ | |
| UTF-16LE | ✅ | |
| UTF-16LE(BOM付き) | ✅ | |
| UTF-16BE | ✅ | |
| UTF-16BE(BOM付き) | ✅ | |
| UTF-32LE | ✅ | |
| UTF-32LE(BOM付き) | ❌ | 文字化け |
| UTF-32BE | ✅ | |
| UTF-32BE(BOM付き) | ✅ | |
| ISO-2022-JP | ✅ | |
| EUC-JP | ✅ |
cmd.exe の type コマンドとリダイレクトは、ファイルの中身をバイト列としてそのまま読み出し、そのまま書き出します。エンコーディングの解釈や変換を行わないため、ほぼすべてのエンコーディングで正常にコピーされます。
唯一 UTF-32LE(BOM付き)だけが文字化けしました。UTF-32LE の BOM は FF FE 00 00 の4バイトですが、先頭の FF FE は UTF-16LE の BOM と同一です。type コマンドが BOM を検出した際に UTF-16LE と誤認し、以降のバイト列の解釈が崩れたものと考えられます。
Windows PowerShell 5.1
| エンコーディング | > |
Set-Content |
Out-File |
|---|---|---|---|
| Shift_JIS | ✅ | ✅ | ✅ |
| UTF-8 | ❌ | ❌ | ❌ |
| UTF-8(BOM付き) | ✅ | ✅ | ✅ |
| UTF-16LE | ❌ | ❌ | ❌ |
| UTF-16LE(BOM付き) | ✅ | ✅ | ✅ |
| UTF-16BE | ❌ | ❌ | ❌ |
| UTF-16BE(BOM付き) | ✅ | ✅ | ✅ |
| UTF-32LE | ❌ | ❌ | ❌ |
| UTF-32LE(BOM付き) | ✅ | ✅ | ✅ |
| UTF-32BE | ❌ | ❌ | ❌ |
| UTF-32BE(BOM付き) | ✅ | ✅ | ✅ |
| ISO-2022-JP | ❌ | ✅ | ❌ |
| EUC-JP | ❌ | ❌ | ❌ |
Windows PowerShell 5.1 では明確なパターンが確認できます。BOM付きファイルはすべて正常に読み込めるが、BOMなしファイルは Shift_JIS 以外すべて文字化けします。 これは PowerShell 5.1 が BOM でエンコーディングを判定し、BOM がない場合はシステムデフォルトの Shift_JIS(cp932)として扱う仕様に起因します。
ISO-2022-JP は Set-Content 経由のみ正常でした。Set-Content は > や Out-File と異なり、バイト列をより素直に書き出す傾向があるためです。
なお、出力エンコーディングについても注目すべき挙動があります。> および Out-File は入力のエンコーディングに関わらず常に UTF-16LE(BOM付き) で出力します。一方、Set-Content は Shift_JIS で出力します。これは PowerShell 5.1 の仕様であり、出力エンコーディングを変更するには -Encoding パラメータの明示的な指定が必要です。
PowerShell 7.5.4
| エンコーディング | > |
Set-Content |
Out-File |
|---|---|---|---|
| Shift_JIS | ❌ | ❌ | ❌ |
| UTF-8 | ✅ | ✅ | ✅ |
| UTF-8(BOM付き) | ✅ | ✅ | ✅ |
| UTF-16LE | ❌ | ❌ | ❌ |
| UTF-16LE(BOM付き) | ✅ | ✅ | ✅ |
| UTF-16BE | ❌ | ❌ | ❌ |
| UTF-16BE(BOM付き) | ✅ | ✅ | ✅ |
| UTF-32LE | ❌ | ❌ | ❌ |
| UTF-32LE(BOM付き) | ✅ | ✅ | ✅ |
| UTF-32BE | ❌ | ❌ | ❌ |
| UTF-32BE(BOM付き) | ✅ | ✅ | ✅ |
| ISO-2022-JP | ✅ | ✅ | ✅ |
| EUC-JP | ❌ | ❌ | ❌ |
PowerShell 7.5.4 では、デフォルトエンコーディングが UTF-8(BOMなし) に変更されました。そのため、5.1 とは逆に Shift_JIS が文字化けし、UTF-8(BOMなし)が正常に処理されます。
BOM付きファイルの扱いは 5.1 と同様で、BOM によるエンコーディング判定が健在です。BOMなしのファイルはデフォルトの UTF-8 として解釈されるため、UTF-8 以外のBOMなしエンコーディングは文字化けします。
また、5.1 では > / Out-File と Set-Content で出力エンコーディングが異なりましたが、7.5.4 ではすべてのコマンドで統一的に UTF-8(BOMなし) で出力されます。
ISO-2022-JP が正常に処理されるのは、Get-Content がバイト列をそのまま通過させた結果と考えられます。
検証2:エンコーディングを明示的に指定した場合の出力
各コンソールでエンコーディングを指定し、日本語テキストをファイルに出力した結果です。
cmd.exe
検証コマンドの例:
chcp 65001
echo "日本語です" > echo_utf-8.txt
cmd.exe では chcp コマンドでコードページを切り替えます。
| エンコーディング | chcp | 結果 | 備考 |
|---|---|---|---|
| Shift_JIS | 932 | ✅ | デフォルト |
| UTF-8 | 65001 | ✅ | |
| UTF-16LE | 1200 | — | Invalid code page |
| UTF-16BE | 1201 | — | Invalid code page |
| UTF-32LE | 12000 | — | Invalid code page |
| UTF-32BE | 12001 | — | Invalid code page |
| ISO-2022-JP | 50222 | ✅ | |
| EUC-JP | 20932 | ✅ |
cmd.exe はシングルバイトおよびダブルバイト系のエンコーディング(Shift_JIS、UTF-8、ISO-2022-JP、EUC-JP)に対応しています。UTF-16 や UTF-32 のようなマルチバイト固定長エンコーディングはコードページとして無効であり、コンソールでは使用できません。
Windows PowerShell 5.1
検証コマンドの例:
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
"日本語です" > test_utf-8.txt
"日本語です" | Set-Content test_utf-8_set.txt
PowerShell では [Console]::OutputEncoding、[Console]::InputEncoding、$OutputEncoding の3つの変数でエンコーディングを設定します。出力は >(Out-File 相当)と Set-Content の2種類で検証しました。
| エンコーディング | > |
Set-Content |
備考 |
|---|---|---|---|
| Shift_JIS | ✅ | ✅ | |
| UTF-8 | ✅ | ✅ | |
| UTF-16LE | ✅ | ✅ | |
| UTF-16BE | — | — | コンソールで使用不可(例外発生) |
| UTF-32LE | — | — | コンソールで使用不可 |
| UTF-32BE | — | — | コンソールで使用不可 |
| ISO-2022-JP | ✅ | ✅ | |
| EUC-JP | — | — | コンソールで使用不可 |
注目すべき点として、エンコーディングを設定しても > の出力は常に UTF-16LE(BOM付き) 、Set-Content の出力は常に Shift_JIS になります。コンソールのエンコーディング設定はファイル出力のエンコーディングには影響しません。ファイルの出力エンコーディングを変更するには、Out-File -Encoding や Set-Content -Encoding のようにコマンドレットの -Encoding パラメータを使用する必要があります。
PowerShell 7.5.4
検証コマンドは Windows PowerShell 5.1 と同様です。
| エンコーディング | > |
Set-Content |
備考 |
|---|---|---|---|
| Shift_JIS | ✅ | ✅ | |
| UTF-8 | ✅ | ✅ | |
| UTF-16LE | ✅ | ✅ | |
| UTF-16BE | — | — | コンソールで使用不可 |
| UTF-32LE | — | — | コンソールで使用不可 |
| UTF-32BE | — | — | コンソールで使用不可 |
| ISO-2022-JP | ✅ | ✅ | 要 CodePagesEncodingProvider 登録 |
| EUC-JP | — | — | コンソールで使用不可 |
PowerShell 7.5.4 でも 5.1 と同様に UTF-16BE、UTF-32、EUC-JP はコンソールエンコーディングとして使用できません。
5.1 との大きな違いとして、> も Set-Content もすべて UTF-8(BOMなし) で出力されます。5.1 と同様、コンソールのエンコーディング設定はファイル出力のエンコーディングには反映されません。
また、ISO-2022-JP を使用する場合は [System.Text.Encoding]::RegisterProvider([System.Text.CodePagesEncodingProvider]::Instance) による登録が事前に必要です。これは PowerShell 7 が .NET(Core)ベースであり、レガシーエンコーディングがデフォルトでは利用できないためです。
まとめ
デフォルト設定での読み込み
3つのコンソール環境のデフォルト設定における読み込み挙動を整理すると、以下のようになります。
| 条件 | cmd.exe | PowerShell 5.1 | PowerShell 7.5.4 |
|---|---|---|---|
| デフォルトエンコーディング | cp932 | cp932 | UTF-8 |
| BOMなし・デフォルトと一致 | ✅ | ✅(Shift_JIS) | ✅(UTF-8) |
| BOMなし・デフォルトと不一致 | ✅(バイトスルー) | ❌ | ❌ |
| BOM付き | ✅(バイトスルー) | ✅ | ✅ |
| UTF-32LE(BOM付き) | ❌(BOM誤認) | ✅ | ✅ |
cmd.exe はエンコーディング変換を行わないバイトスルー方式のため、ほぼすべてのファイルをそのまま通過させます。PowerShell は読み込み時にエンコーディングを解釈するため、BOMなしファイルでデフォルトと異なるエンコーディングは文字化けします。
デフォルト設定での出力エンコーディング
| コマンド | cmd.exe | PowerShell 5.1 | PowerShell 7.5.4 |
|---|---|---|---|
> リダイレクト |
入力と同一(バイトスルー) | UTF-16LE(BOM付き) | UTF-8(BOMなし) |
Set-Content |
— | Shift_JIS | UTF-8(BOMなし) |
Out-File |
— | UTF-16LE(BOM付き) | UTF-8(BOMなし) |
実務上の指針
cmd.exe はエンコーディング変換を行わないため、ファイルのコピーやリダイレクトでは最も安全です。ただし UTF-32LE(BOM付き)は BOM の誤認により文字化けするので注意が必要です。
Windows PowerShell 5.1 を使用する場合、BOMなしの UTF-8 ファイルを扱うには -Encoding UTF8 を明示する必要があります。また、> の出力が UTF-16LE(BOM付き)になることを認識しておくべきです。
PowerShell 7.5.4 はデフォルトが UTF-8 に統一されており、現代の開発環境では最も扱いやすい選択です。ただし、レガシーな Shift_JIS ファイルを扱う場合は -Encoding パラメータでの明示的な指定が必要になります。
BOMなしのファイルを確実に扱うには、どのコンソール環境でも -Encoding パラメータなどでエンコーディングを明示的に指定することが推奨されます。