UTF-8の文字化けを直す|Windows・Markdown・ターミナルの確認手順

UTF-8の文字化けを、発生箇所、ファイルの実体、BOM、ターミナル、読み書き処理の順に切り分け、安全に直して差分を検査する手順を解説します。

UTF-8の文字化けには、元ファイルは正常で表示設定だけが違う場合と、誤った文字コードで保存された場合があります。最初に原本をコピーし、「どこで初めて崩れたか」を切り分けてから修正します。

症状別の確認先

症状考えられる箇所最初にする確認この時点で避ける操作
エディターでは正常、ターミナルだけ崩れるコンソールのコードページ、フォント、コマンドの入出力chcp、PowerShellの版、-Encoding utf8 指定時との比較原本の上書き保存
どのアプリでも同じように崩れるファイルの保存時に使われた文字コード別名コピーを作り、16進表示と作成元を確認推測した文字コードで保存を繰り返す
.md は正常、生成後HTMLだけ崩れるビルド処理、HTTPヘッダー、HTMLの文字コード宣言生成HTMLとレスポンスの Content-Type を確認Markdown原本の変換
先頭だけに不要な文字が出るBOMの扱い先頭3バイトが EF BB BF か確認BOMを原因と決めつけて削除
が混じるデコーダーが不正なバイト列を置換した可能性変換前の原本を確保し、読み取り時の文字コードを確認 を元の文字として一括置換

文字化けの発生箇所を特定する

同じファイルをエディター、PowerShell、ブラウザやビルド結果で開きます。エディターだけ正常ならターミナルの表示設定を疑い、どこでも崩れるなら保存時の文字コードを調べます。Markdownも、元の .md と生成後HTMLを分けてください。

修正前に対象を複製し、原本へ「別の文字コードで保存」を繰り返さないでください。誤った解釈のまま保存すると、設定変更だけでは戻せなくなる場合があります。パスも怪しい場合は、Windowsのパスエラーを直す手順で問題を分けます。

メモには対象ファイル、正常・異常だったアプリ、保存操作の有無を残します。「何として読み、何で書いたか」まで記録します。

ファイルの文字コードを確認する

拡張子が .md.txt でも、文字コードは確定しません。VS Code公式資料では、ステータスバーから別の文字コードで開き直す操作と保存する操作を選べます。最初は保存せず「エンコード付きで再度開く」で候補を試します。

PowerShellでは、ファイルの先頭を16進数で見ると手掛かりになります。

Format-Hex -LiteralPath .\sample.md | Select-Object -First 4

Format-Hexはファイルを16進値で表示します。ただし、BOMがないファイルの文字コードを常に一意に判定できるわけではありません。作成元のアプリや直前の正常な版も調べます。JSONなら、文字コードを直した後にJSONエラーの原因行を探す手順で構文も検査できます。

BOMありなしを見分ける

BOM(バイト順マーク)はファイル先頭の印です。Unicode Consortiumの公式FAQでは、UTF-8のBOMは EF BB BF で、UTF-8だと示す署名として使われます。先頭がこの3バイトならBOMあり、なければBOMによる判定はできません。

$bytes = [System.IO.File]::ReadAllBytes('.\sample.md')
$bytes[0..([Math]::Min(2, $bytes.Length - 1))] |
  ForEach-Object { $_.ToString('X2') }

BOMの有無は受け取るツールに合わせます。Microsoft公式資料では、PowerShell 6以降のテキスト出力は既定でUTF-8 BOMなしです。一方、Windows PowerShellは非ASCII文字を含むBOMなしスクリプトを従来のANSIコードページとして誤解する場合があります。

と読めない文字列を区別する

はUnicodeの置換文字(U+FFFD)です。WHATWGのEncoding Standardでは、デコーダーがエラーを置換するモードでU+FFFDを出力すると定義されています。そのため、があるときは「表示フォントだけの問題」とは限らず、読み取り時点で元のバイトを正しく文字へ変換できなかった可能性があります。

一方、縺薙s縺ォ縺。縺ッのように別の文字列として読める場合は、UTF-8のバイト列をShift_JIS系として解釈したなど、文字コードの組み合わせがずれた可能性があります。見た目だけから変換方向を断定せず、元ファイルのコピー、作成元、直前の正常な版をそろえて判断します。

ターミナルの表示設定を確認する

ファイルがエディターでは正常なのにターミナルだけ崩れるなら、保存し直す前に表示側を確認します。コマンドプロンプトでは次のコマンドで、現在のコンソールコードページを表示できます。

chcp

Microsoft公式資料によると、chcpは引数なしで現在値を表示し、変更後に起動したプログラムは新しい設定を使います。既に起動中の一部プログラムには反映されません。コンソール設定を変えても、誤って保存済みのファイルは直りません。

PowerShellの版も記録します。

$PSVersionTable.PSVersion
Get-Content -LiteralPath .\sample.md -Encoding utf8

版によって既定動作が異なるため、-Encoding utf8 を明示して比較します。明示時だけ正常なら、暗黙の既定値が原因の可能性があります。

ブラウザだけ文字化けする場合を確認する

Markdown原本が正常でも、生成後HTMLの宣言と実際のバイト列が一致しなければブラウザ表示は崩れます。HTML Standardでは、meta要素の charset 属性は文書の文字エンコーディングを宣言し、値には大文字小文字を区別せず utf-8 を指定すると定めています。

<meta charset="utf-8">

生成HTMLの <head> だけでなく、開発者ツールなどでHTTPレスポンスの Content-Type も確認します。HTML側をUTF-8と宣言するだけでは、別の文字コードで保存されたファイル自体は直りません。frontmatterが崩れてビルドに失敗する場合は、文字コードを直してからMarkdownのfrontmatterエラーを直す手順で区切りや値を確認します。

読み書き時のencodingを指定する

正しい文字コードで読めると確認してから、コピー先へ保存します。VS Codeなら正しい候補で開き直し、内容を見てから「エンコード付きで保存」でUTF-8を選びます。

PowerShell 7では、読み込みと書き込みの両方へエンコードを明示できます。

$text = Get-Content -LiteralPath .\sample.md -Raw -Encoding utf8
Set-Content -LiteralPath .\sample.fixed.md -Value $text -Encoding utf8NoBOM

この例は入力がUTF-8だと確認済みの場合だけ使います。別の文字コードなら、正しく開けることを先に確認し、別名へ保存します。PowerShell公式資料では Get-ContentSet-ContentOut-Fileなどが Encoding を持ちます。版の既定値に任せず明示すると再現しやすくなります。

修正後に差分を検査する

修正後は、行数、見出し、URL、コードブロック、frontmatterを比較します。Markdownでは ---、引用符、コロンも確認します。大量置換や改行コード変更が混ざったら、文字コード修正とは分けます。

$before = Get-Content -LiteralPath .\sample.md -Encoding utf8
$after  = Get-Content -LiteralPath .\sample.fixed.md -Encoding utf8
Compare-Object -ReferenceObject $before -DifferenceObject $after

入力が元からUTF-8なら、本文差分は意図したものか確認します。最後にエディター、ターミナル、ビルド処理で再確認し、合格後に原本と入れ替えます。原本コピーは復旧できるまで残します。

よくある質問

UTF-8に変換すれば、文字化けは必ず元に戻りますか

戻るとは限りません。誤った文字コードで読み込んだだけなら、正しい指定で開き直せる可能性があります。誤った状態で上書きされ、元のバイトが失われている場合は、バックアップや履歴からの復旧が必要です。

UTF-8はBOMありとBOMなしのどちらを選べばよいですか

受け取るツールやファイル形式の仕様に合わせます。UTF-8のBOMは EF BB BF ですが、Unicode Consortiumは、BOMを想定しない受信側や先頭のASCII文字に意味がある形式では干渉し得ると説明しています。判断できないときは既存の正常なファイルとプロジェクトの規約を確認します。

chcp 65001を実行すればファイルもUTF-8になりますか

なりません。chcpが変更するのはコンソールのコードページです。既に別の文字コードで保存されたファイルのバイト列は変わらないため、表示設定とファイル変換を分けて扱います。

VS Codeで正しく見えるのに、サイトだけ文字化けするのはなぜですか

生成処理、生成後HTML、HTTPレスポンスのいずれかで文字コードの扱いが変わっている可能性があります。元のMarkdown、生成HTML、ブラウザが受け取った Content-Type の順に確認します。

を正しい文字へ一括置換してもよいですか

通常は避けます。だけでは元の文字を一意に決められません。変換前の原本や履歴を確保し、どの文字コードとして読んだときに置換されたのかを先に調べます。

一次情報

調査時に確認した公式資料:

続き(結論と実データ)はnoteに置いています

ここでは手順のところまで書きました。実際に出た数字、うまくいかなかった条件、そのまま使える設定ファイルは、 note の記事にまとめてあります。

noteで続きを読む Xをフォローする