UTF-8 以外のエンコーディング指定

概要

HtmlAgilityPack (HAP) でドキュメントを保存 (Save)/出力する際の既定エンコーディングは UTF-8 です。
しかし、Encoding オブジェクトを明示的に指定すれば Shift-JIS や EUC-JP、ISO-8859-1 など任意のコードページで書き出せます。本回答では以下を中心に解説します。

  1. 既定動作と HtmlDocument.Encoding の役割

  2. 同期 Save 系 API での指定方法

  3. 非同期 SaveAsync 系 API での指定方法

  4. .NET 6+(.NET Core 系列)でのコードページ有効化

  5. <meta charset>Content-Type メタタグとの整合性

  6. よくある落とし穴と対策

  7. まとめ & サンプルコード全体


1. 既定動作と HtmlDocument.Encoding の役割

タイミング 設定される値 説明
ロード時 HtmlDocument.Encoding BOM・HTTP ヘッダ・<meta charset> を解析して決定。判定不能なら UTF-8。
保存時 1) Save(..., Encoding) 引数
2) HtmlDocument.Encoding プロパティ
1 が指定されればそれが優先。省略すると 2 が使われ、値が null のときは UTF-8。

ポイント

  • 読み込み後に doc.Encoding = Encoding.GetEncoding("shift_jis"); のように上書きすれば、その値が保存時の既定値になる。

  • 変換時に再エンコードされるため、文字化けを防ぐには 保存前に プロパティを設定する。


2. 同期 Save 系 API での指定方法

オーバーロード 主な用途
Save(string filePath, Encoding enc) 手軽にファイルへ出力 doc.Save("out_sjis.html", Encoding.GetEncoding("shift_jis"));
Save(Stream stream, Encoding enc) MemoryStream 経由やネットワーク送出 doc.Save(mem, Encoding.GetEncoding("windows-1252"));
Save(TextWriter writer) StreamWriter に依存 using var w = new StreamWriter(path, false, enc); doc.Save(w);

注意点

  • BOM 付与Encoding が UTF-16/UTF-32 系の場合は BOM が出力される。Shift-JIS などには BOM が存在しない。

  • 改行コード:HAP は改行コードを強制変更しない。必要なら TextWriter.NewLine を設定する。


3. 非同期 SaveAsync 系 API

最新版 (v1.11.x 系以降) では下記のようなオーバーロードがあります。

csharp
Task SaveAsync(string filePath, Encoding enc, CancellationToken token = default); Task SaveAsync(Stream stream, Encoding enc, CancellationToken token = default);

使い方は同期版と同じで、第 2 引数に Encoding を渡すだけです。
I/O バウンドの Web API 内部や GUI アプリで UI スレッドをブロックさせたくない場合に有効です。


4. .NET 6+ (.NET Core 系) でのコードページ有効化

.NET Core では歴史的コードページ (Shift_JIS、EUC-JP など) が既定で無効化されています。
利用前に下記 1 行を必ず実行してください。

csharp
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

これを呼ばずに Encoding.GetEncoding("shift_jis") を行うと System.ArgumentException が発生します。


5. <meta charset>Content-Type メタタグとの整合性

  • HAP は HtmlDocument.Encoding を変更しただけでは 既存の <meta charset> を自動更新しない 場合があります。

  • 安全策として、保存前に以下のようにヘッダを書き換えるか新規挿入してください。

csharp
var head = doc.DocumentNode.SelectSingleNode("//head") ?? doc.DocumentNode.PrependChild(doc.CreateElement("head")); var meta = head.SelectSingleNode("meta[@charset]") ?? doc.CreateElement("meta"); meta.Attributes.RemoveAll(); meta.Attributes.Add("charset", doc.Encoding.WebName); head.PrependChild(meta);

これでブラウザ読込み時の文字化けを防止できます。


6. よくある落とし穴と対策

症状 原因 対策
保存後に一部文字が ? になる ターゲットエンコーディングが当該文字を収容できない 日本語なら Shift-JIS → UTF-8、絵文字を含むなら UTF-8 に切替
Encoding.GetEncoding が例外 .NET Core でコードページ未登録 Encoding.RegisterProvider(...) を呼ぶ
ブラウザ表示で文字化け <meta charset> が旧値のまま 5 章のようにメタタグを更新
SaveAsync が存在しない 古い HAP バージョン NuGet で HtmlAgilityPack を 1.11 以降に更新

7. まとめ & サンプルコード全体

csharp
// .NET 6+ / C# 10 using HtmlAgilityPack; using System.Text; Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // ❶ var doc = new HtmlDocument(); doc.Load("input.html"); // ❷ doc.Encoding = Encoding.GetEncoding("shift_jis"); // ❸ // 文字化け防止のため <meta charset> を更新 var head = doc.DocumentNode.SelectSingleNode("//head") ?? doc.DocumentNode.PrependChild(doc.CreateElement("head")); var meta = head.SelectSingleNode("meta[@charset]") ?? doc.CreateElement("meta"); meta.Attributes.RemoveAll(); meta.Attributes.Add("charset", doc.Encoding.WebName); head.PrependChild(meta); // ❹ await doc.SaveAsync("output_sjis.html", doc.Encoding); // ❺
  1. コードページ登録

  2. HTML 読込み(LoadHtml(string)Load(Stream) も可)

  3. 保存時に使用したいエンコーディングを設定

  4. メタタグをドキュメントに反映

  5. 非同期で Shift-JIS エンコードのファイルを書き出し

この手順を押さえておけば、UTF-8 以外のエンコーディングでも安全かつ確実にドキュメントを保存・出力できます。

ChatGPT4o 生成日:2025/06/23