個人的によく(解決方法を)聞かれる&報告される不具合TOP3に入る「文字化け問題」。
日本語のCSVやテキストを読み込んだら、「 」や謎の記号だらけになった。いわゆる文字化け。大体はファイルの文字コードと、読み込み時に想定している文字コードのズレが原因。
原因:読み込み時のエンコードが合っていない
日本語のテキストファイルは主にShift-JISかUTF-8で保存されている。一方、.NETのFile.ReadAllText(path)はエンコードを指定しないと基本UTF-8として読む。だからShift-JISのファイルをそのまま読むと化ける。
解決:Encodingを明示して読み込む
読み込むファイルの文字コードに合わせて、Encodingを指定してあげればいい。
// UTF-8のファイルを読む
string textUtf8 = File.ReadAllText(path, Encoding.UTF8);
問題はShift-JIS。.NET Core / .NET5以降ではShift-JISが標準で使えないので、そのままEncoding.GetEncoding("shift_jis")と書くと例外になる。最初にプロバイダを登録してから使う。
using System.Text;
// .NET Core / .NET8 でShift-JISなど日本語コードを使うための「おまじない」
// (事前に NuGet で System.Text.Encoding.CodePages を追加)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// これでShift-JISが使えるようになる
Encoding sjis = Encoding.GetEncoding("shift_jis");
string textSjis = File.ReadAllText(path, sjis);
RegisterProviderはアプリ起動時に1回呼べばOK。以降はGetEncoding("shift_jis")やGetEncoding(932)が使える。
書き出し時の注意:UTF-8のBOM
書き出す側にもハマりポイントがある。UTF-8で書いたCSVをExcelで開くと文字化けする件。これはExcelがBOM無しUTF-8をShift-JISと誤認するのが原因。BOM付きUTF-8で書き出すと、Excelでも正しく開ける。
// BOM付きUTF-8(先頭にBOMを付ける → Excelで開いても化けにくい)
var utf8Bom = new UTF8Encoding(true);
File.WriteAllText(path, csvText, utf8Bom);
// BOM無しUTF-8にしたい場合は false
var utf8NoBom = new UTF8Encoding(false);
逆に、システム間連携ではBOMが邪魔になるケースもあるので、相手が何を期待しているかで付け外しを決める。
さいごに
文字化けは「読み書き両方でEncodingを合わせる」のが全て。迷ったら、相手のファイルがShift-JISかUTF-8か、BOMの有無を先に確認するのが早い。
Shift-JISを扱うプロジェクトでは、起動時のRegisterProviderを忘れずに。これだけで「なぜかGetEncodingで落ちる」を回避できる。
あとよくあるのが、誰かがメモ帳でファイルを開いて上書き保存しただけで文字コードが変わってしまうパターン。
Windows11のメモ帳はデフォルトの保存文字コードがUTF-8なので、元がShift-JISのファイルでも一度開いて保存し直すとUTF-8になっていたりする(Windows10以前は逆にANSI=Shift-JIS保存がデフォルトだった)。
「昨日まで動いてたコードが急に文字化けするようになった」ときは、バグを疑う前に誰かがメモ帳で開いて保存し直していないかを確認すると早い。


コメント