-
Notifications
You must be signed in to change notification settings - Fork 0
MS_Encoding
- 戻る(文字コード)
- エンコーディングとは【encoding】(エンコード) - 意味-解説-説明-定義 : IT用語辞典
https://e-words.jp/w/E382A8E383B3E382B3E383BCE38387E382A3E383B3E382B0.html- 情報を一定の規則に従ってデータに置き換えて記録すること。
- ある形式のデータを一定の規則に基づいて別の形式のデータに変換すること。
- (文字エンコーディングだけでなく、)データ圧縮や暗号化などもこれに含まれる。
余談:・・・となると、
Stream に Decorate パターンを適用する
殆どの処理が=エンコーディングと言う事になる。
補足(原文の「余談」は的を射ている): .NET の
Streamは
Decorator パターンで設計されており、
「変換」を層として重ねる構造になっている。// 圧縮 → 暗号化 → 文字エンコーディング を重ねる using var file = File.Create("data.bin"); using var crypto = new CryptoStream(file, encryptor, CryptoStreamMode.Write); using var gzip = new GZipStream(crypto, CompressionMode.Compress); using var writer = new StreamWriter(gzip, Encoding.UTF8); writer.Write("本文");【層の重なり】 string(文字) ↓ StreamWriter(文字エンコーディング) byte[] ↓ GZipStream(データ圧縮) byte[] ↓ CryptoStream(暗号化) byte[] ↓ FileStream(永続化)どの層も「バイト列 → バイト列」の変換であり、
文字エンコーディングだけが特別なわけではない、
という原文の指摘はそのまま正しい。
文字エンコーディングは「最上層=文字とバイトの境界」に位置する点だけが
他と異なる(ここだけstringが絡む)。
ココでは各種、文字エンコーディングの情報を纏めています。
「外字」については、「Windowsの外字」を参照下さい。
文字エンコーディングとは、文字列データを、
異なる文字コード(コードページ)を使用したバイト表現に変換することである。
- 文字コード - Wikipedia
https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89 - コードページ - Wikipedia
https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%9A%E3%83%BC%E3%82%B8
補足(用語の整理): 「文字コード」という語は複数の層を混ぜて
使われるため、混乱の元になる。厳密には 3 層に分かれる。
層 意味 例 符号化文字集合(Coded Character Set) 「どの文字に、どの番号を振るか」 JIS X 0208、Unicode、ASCII 文字符号化方式(Character Encoding Scheme) 「その番号を、どうバイト列にするか」 Shift_JIS、EUC-JP、UTF-8、UTF-16 コードページ Microsoft / IBM が符号化に振った番号 932(CP932)、65001(UTF-8) 【Unicode の場合】 文字「あ」 ↓ 符号化文字集合(Unicode)が番号を決める U+3042(コードポイント) ↓ 文字符号化方式が バイト列にする UTF-8 → E3 81 82(3 バイト) UTF-16 → 42 30(リトルエンディアン、2 バイト) UTF-32 → 42 30 00 00(4 バイト)「Unicode」と「UTF-8」は同じ層のものではない。
Unicode は文字集合、UTF-8 はその符号化方式である。
Windows が言う「Unicode」は、多くの場合 UTF-16 LE を指す
(Encoding.Unicodeが UTF-16 LE であるのはこのため)。
文字化けは、一般的に、
- エンコーダに適切な文字コード(コードページ)を指定していない
- プラットフォームやユーザ間で使用している外字が異なる
- コードページによっては、変換が不可逆なケースがある
際に発生します。
文字コード(コードページ)指定を大きく誤っている場合は、すぐ気が付くのですが、
- UTF-16(Unicode)
- UTF-8
- Shift JIS
- EUC-JP
一部だけ文字化けする場合のトラブルシュートは苦戦することが多いです。
一部だけ文字化けするパターンは以下の様に分類できると考えます。
-
文字コード(コードページ)指定を大きく間違えていない(微妙に間違っている)
- 例えば、Shift_JIS の亜種のコードページ指定を誤っている。
- ISO-2022-JP
- Microsoft コードページ932(CP932)
- MacJapanese
- 例えば、Shift_JIS の亜種のコードページ指定を誤っている。
-
外字領域の定義(見た目)が異なっている。
- この場合、データのエンコード自体は正しく行われている。
- 人間にとっての見た目が、異なっているため文字化けと感じられる。
- 外字についてはこちらを参照:「Windowsの外字」
補足(この分類は今も有効): 「大きく間違えた文字化け」と
「一部だけの文字化け」を分けるという原文の視点は、
障害切り分けの手順としてそのまま使える。
症状 原因の見当 全部が化ける(「譁�ュ怜喧縺�」等) エンコーディングの指定違い。まず疑う 全部が ?になる変換先に存在しない文字(例:UTF-8 → ASCII) 一部の記号だけ化ける(〜、−、①、㈱) CP932 の亜種違い、または波ダッシュ問題(事例4) 一部の漢字だけ化ける(髙、﨑) 外字・機種依存文字、または JIS2004 □や・で表示されるフォントにその字がない(データは正しい) 1 文字が 2 文字に見える サロゲート ペアの扱い(文字のチェック方式) 最後の 2 つは「文字化け」ではない点が重要である。
データは正しく、表示側の問題なので、
データを直そうとすると事態が悪化する。
従って、以下に注意を払う必要があります。
-
プラットフォーム
- 実装されている文字コード(コードページやフォント)
- 適用される標準のエンコーディングが何か?
- フォントや外字がインストールされているか?
-
エンコーディングが動作する箇所
-
ファイル I/O
-
SGML 文書の I/O
- HTML 出力
- XML 入出力
-
ファイル転送(プロトコルに実装されているケース)
- SFU(Microsoft Windows Services for UNIX)
- FTP(ASCII モード)
-
データベースの I/O
Unicode 文字列以外のフィールドから入出力する場合、
通常、照合順序で指定したに対応した文字コード(コードページ)
を使用して、エンコード・デコードされる。
-
補足(「エンコーディングが動作する箇所」の現在版): 原文の
**「境界を数え上げる」**という発想が本質で、
現在のシステムでも同じ手順で洗い出せる。【文字とバイトの境界=エンコーディングが働く場所】 ① ファイル I/O … StreamReader/Writer の encoding 引数 ② HTTP … Content-Type の charset、URL エンコード ③ HTML / XML / JSON … 宣言と実体の不一致 ④ データベース … 列の型(varchar / nvarchar)と照合順序 ⑤ コンソール … Console.OutputEncoding、端末のコードページ ⑥ プロセス間 … 標準入出力のリダイレクト、引数 ⑦ 圧縮ファイル … ZIP のファイル名のエンコーディング(!) ⑧ メール … MIME のヘッダとボディ ⑨ CSV / 固定長ファイル … BOM の有無、改行コード**現在の指針は「境界を減らす」**である。
・内部は常に UTF-16(.NET の string)で扱う ・外部との入出力は【原則 UTF-8】に統一する ・変換が必要な箇所を【システムの端に集約する】 → 中間層で変換すると、どこで壊れたか分からなくなる⑦ ZIP のファイル名は現在も事故が多い。
古い ZIP はファイル名を CP932 で持つため、
UTF-8 前提のツールで開くと化ける(逆も同じ)。// .NET で CP932 のファイル名を持つ ZIP を読む ZipFile.ExtractToDirectory("a.zip", "out", Encoding.GetEncoding(932));
プラットフォームに実装されている文字コード(コードページやフォント)に起因する文字化け。
-
Microsoft コードページ932 - Wikipedia
https://ja.wikipedia.org/wiki/Microsoft%E3%82%B3%E3%83%BC%E3%83%89%E3%83%9A%E3%83%BC%E3%82%B8932-
インターネット上での Windows-31J の利用について ~ NEC 特殊文字・IBM 拡張文字
- IBM 拡張文字等の Windows-31J 独自追加の文字は、
他の JIS X 0208 非登録の CJK 統合漢字に比べて、
異機種(OS / アプリケーション)間でのデータ交換を、
文字化けを起こしたりせずにデータのやり取りが正常に行える確率が高い。 - しかし、JIS X 0208 非登録の文字をサポートしない環境があることを考えると、
JIS X 0208 登録文字だけを用いてデータ交換を行った方が、問題が起こりにくい。
- IBM 拡張文字等の Windows-31J 独自追加の文字は、
-
JIS X 0208 - Wikipedia
https://ja.wikipedia.org/wiki/JIS_X_0208
-
-
Windowsの機種依存文字 - CyberLibrarian
http://www.asahi-net.or.jp/~ax2s-kmtn/ref/mdc.html- NEC 機種依存文字
- NEC の IBM 拡張文字
- IBM 拡張文字
補足(機種依存文字の実際): CP932 が JIS X 0208 に追加した領域が
事故の温床である。
領域 内容 例 NEC 特殊文字(13 区) 丸数字、ローマ数字、単位記号 ① ② Ⅰ Ⅱ ㈱ ℡ № NEC 選定 IBM 拡張文字(89~92 区) IBM 拡張文字の重複定義 兊 兤 冝 … IBM 拡張文字(115~119 区) 人名・地名の漢字、記号 髙 﨑 彅 纊 NEC 選定 IBM 拡張文字と IBM 拡張文字は、
同じ文字に 2 つのコードが割り当てられている(重複符号化)。
これが往復変換で値が変わる原因になる。「兊」を Unicode → CP932 に変換すると 0xFA5C(IBM 拡張)になるが、 元データが 0xED40(NEC 選定)だった場合、値が変わって戻る → バイト列で比較する処理(チェックサム、重複判定)が壊れる原文の結論——「JIS X 0208 登録文字だけを用いる」——は
データ交換の指針としては今も正しい。
ただし現実には、氏名に「髙」「﨑」が入るため避けられない。
現在の解は、システム全体を UTF-8 / Unicode で通すことである
(アプリケーションのUnicode化)。
プラットフォームで適用される標準のエンコーディングに起因する文字化け。
-
@IT:事例に学ぶWebシステム開発のワンポイント(8)
http://www.atmarkit.co.jp/fjava/rensai2/webopt08/webopt08.html#ap04- .NET では標準で、Shift_JIS = MS932 となるが、
- Java では Shift_JIS ≠ MS932 となるため、
補足(この差は今も残っている): 原文の指摘は現在も有効で、
.NET と Java の異種混在システムで実際に起こる。
指定 .NET Java "Shift_JIS"CP932 と同じ(= MS932) JIS X 0208 準拠。機種依存文字が化ける "MS932"(この名前は使わない) CP932 相当 "Windows-31J"CP932 CP932 相当 【事故のパターン】 .NET 側: Encoding.GetEncoding("Shift_JIS") で「①」を書き出す → 0x8740(CP932 として正しい) Java 側: new String(bytes, "Shift_JIS") で読む → 「?」になる(JIS X 0208 に ① がないため) 【対策】 Java 側で "Windows-31J" を明示するエンコーディング名は「別名」が多く、実体が処理系で異なる——
これが教訓である。
曖昧さのない名前(Windows-31J、UTF-8)を使い、
両システムの実装を確認する。
フォントや外字のインストール状況に起因する文字化け。
- こちらを参照:「Windowsの外字」
コードページによっては、変換が不可逆なケースがある。
-
JA16SJIS → Unicode 方向への変換において、
Unicode の文字データに U+FF5E が渡されると 0x8160 に変換される。 -
逆向きの JA16SJIS → Unicode 方向への変換において、
JA16SJIS の入力データに 0x8160 が渡されると、U+FF5E ではなく U+301C に変換される。
この変換はあくまでも Unicode から JA16SJIS 方向への片方向の変換においてのみ適用される。
移行メモ(原文の方向表記が入れ替わっている): 原文は
**1 番目も 2 番目も「JA16SJIS → Unicode 方向」と書いているが、
内容から見て1 番目は「Unicode → JA16SJIS 方向」**が正しい
(「Unicode の文字データに U+FF5E が渡されると」とあるため)。
最終行の「Unicode から JA16SJIS 方向への片方向の変換」という記述とも整合する。この現象は「波ダッシュ問題」として知られる、
日本語システムで最も有名な文字化けである。【問題の構造】 Shift_JIS の 0x8160(1 バイト目 0x81、2 バイト目 0x60) ↓ この 1 文字に、Unicode の候補が 2 つある U+301C 〜 WAVE DASH(波ダッシュ) ← JIS の規格上はこちら U+FF5E ~ FULLWIDTH TILDE(全角チルダ) ← Microsoft はこちらに対応付けた
対応付け 採用している処理系 0x8160 ↔ U+FF5E Windows / .NET(CP932)、多くの Windows アプリ 0x8160 ↔ U+301C Java の Shift_JIS、Unix 系、Oracle の JA16SJIS、iOS/macOS 同じ「〜」に見えるのに、バイト値が違うため、
・文字列比較が一致しない(見た目は同じなのに) ・DB の検索でヒットしない ・往復変換で別の文字になる ・Windows で入力したデータを Oracle に入れると化ける同種の問題を起こす文字(Unicode 対応が 2 通りある):
文字 JIS 系 Microsoft 系 〜(波ダッシュ) U+301C U+FF5E ‖(双柱) U+2016 U+2225 −(負符号) U+2212 U+FF0D ¢ £ ¬ U+00A2 U+00A3 U+00AC U+FFE0 U+FFE1 U+FFE2 現在の対策:
① 【システム全体を UTF-8 に統一する】 → 変換自体をなくす。最も確実 ② 変換が避けられないなら、【正規化テーブルを持つ】 → 入力時に U+FF5E → U+301C 等へ寄せる(どちらかに統一) ③ 【Unicode 正規化(NFKC)を掛ける】 → ただし NFKC は全角英数を半角にする等、影響が広い。要注意// ② の例:入力時に波ダッシュ系を統一する static string NormalizeWaveDash(string s) => s .Replace('~', '〜') // ~ → 〜 .Replace('-', '−') // - → − .Replace('∥', '‖'); // ∥ → ‖
-
サポートするコード ページ
https://learn.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers -
Microsoft コードページ932 - Wikipedia
https://ja.wikipedia.org/wiki/Microsoft%E3%82%B3%E3%83%BC%E3%83%89%E3%83%9A%E3%83%BC%E3%82%B8932-
CP932 の呼称(別名)の整理
-
Windows-31J
Windows 3.1 (J) のリリースに合わせて、マイクロソフトが
IBM と日本電気 (NEC) のコードを統合して作った符号化文字集合。
1993 年以降、マイクロソフトが自社のドキュメント等で「CP932」という用語を使って
表している対象は、常にこの「Windows-31J」である。この名前は IANA に登録されている。 -
MS932
Java で、「IBM のコードページ 932」と「Windows-31J」を区別するための用語。 -
CP932
MS-DOS と Windows における日本語コードページを表す用語。
「Windows-31J」が制定されるまでは、OEM ベンダによって文字集合が違う。 -
MS 漢字コード
「CP932」とほぼ同じ意味の用語である。
マイクロソフトが(Shift_JIS という符号化方式を)策定したという点や、
マイクロソフトが(JIS X 0208 という文字集合に対して)文字を独自に追加した点を
強調したい場合に用いられる。また、単に「シフト JIS」のことを指している場合もある。 -
OEM コードページ 932
Windows 3.1 日本語版の発売以前における、OEM ベンダ各自の拡張を許した仕様の文字セット。
以下は、マイクロソフトから離れ、現在では公的機関からも認められた文字符号化方式を指す用語。 -
シフト JIS
JIS X 0208 符号化文字集合を一定の規則に従ってシフトした文字符号化方式。
具体的な内容は JIS X 0208:1997 に「シフト符号化表現」として記載がある。
しかし、文脈によってはベンダ拡張されたコードセットを指している場合もある。 -
Shift_JIS
「シフト JIS」の IANA 登録名。 -
SJIS
Shift_JIS の短縮形。Java では Shift_JIS と同義語。
-
-
移行メモ(
SJISは Java では Shift_JIS と同義ではない): 原文の
最終行は正確でない。Java のSJISはShift_JISの別名として
扱われるが、事例2で述べた通り、
Shift_JIS自体が CP932 とは異なるため、
「同義語」という表現は誤解を招く。
Java で CP932 相当を使いたければWindows-31JまたはMS932を指定する。
補足(.NET でコードページを使う際の必須手順): .NET Core 以降、
Encoding.GetEncoding(932)は既定では失敗する。// ✗ .NET Core / .NET 5+ では ArgumentException var enc = Encoding.GetEncoding(932); // ○ プロバイダーを登録してから使う // NuGet: System.Text.Encoding.CodePages Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); var enc = Encoding.GetEncoding(932);.NET Framework には全コードページが組み込まれていたが、
.NET Core 以降は UTF 系と ASCII / Latin-1 のみが標準で、
それ以外は上記のパッケージが要る(クロス プラットフォーム化のため)。主なコードページ:
番号 名前 内容 932 Shift_JIS / Windows-31J 日本語(CP932) 20932 EUC-JP 日本語(Unix 系) 50220/50222 ISO-2022-JP JIS コード(メールで使われた) 1252 Windows-1252 西欧 65001 UTF-8 既定にすべきもの 1200 UTF-16 LE Windows の内部表現( Encoding.Unicode)
Encoding.Defaultの意味も変わった点に注意する。
.NET Framework .NET Core 以降 Encoding.DefaultOS の ANSI コードページ(日本語なら CP932) 常に UTF-8 旧コードから移植する際、
Encoding.Defaultが
暗黙に CP932 を意味していた箇所は全て壊れる。
移植時は明示的にEncoding.GetEncoding(932)へ置き換える。
文字参照(数値文字参照・文字実体参照)のエンコーディング(エスケープ)を行う。
- 文字参照 - Wikipedia
https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E5%8F%82%E7%85%A7\ 直接記述できない文字や記号を HTML・XML 上に表記、参照するため用いられる方法。-
マークアップで使われる、半角の不等号「<」や「>」
-
指定の文字コードで表現できない文字を表記、参照する。
-
表記方法により「数値文字参照」と「文字実体参照」の二種が存在する。
-
数値文字参照
10 or 16 進数で該当文字を ISO 10646 の文字番号で指定する方法。
指定の文字コードで表現できない文字を表記、参照する。 -
文字実体参照
特定のキーワード文字列で該当文字(主にマークアップで使われる文字)を指定する方法。
XSS(クロスサイト・スクリプティング)対策としても使用される。
-
-
補足(エスケープの正しい考え方): 原文は
「XSS 対策としても使用される」と書いているが、
ここは現在の理解に沿って整理しておく必要がある。**XSS 対策の本質は「出力先の文脈に応じたエスケープ」**であり、
HTML エスケープさえすれば安全、ではない。
出力先(文脈) 必要なエスケープ HTML の本文 < > & " '→ 文字参照HTML の属性値 上記+必ず引用符で囲う <script>の中JavaScript のエスケープ(HTML エスケープでは不十分) URL の一部 URL エンコード(後述) CSS の中 CSS のエスケープ <a href>の値スキームを検証( javascript:を弾く)<!-- HTML エスケープしても防げない例 --> <a href="javascript:alert(1)">クリック</a>.NET での実装:
// 文脈ごとに使い分ける HttpUtility.HtmlEncode(s); // HTML 本文・属性 HttpUtility.JavaScriptStringEncode(s); // <script> 内 HttpUtility.UrlEncode(s); // URLASP.NET Core の Razor では
@値が自動的に HTML エスケープされる
ため、手でエスケープしないのが原則である
(二重エスケープになる)。
危険なのは@Html.Raw()を使った箇所だけ、という状態に保つ。
HTTP ヘッダか、meta タグにエンコーディングを指定することで
WWW ブラウザがデコードする際に指定する文字コード(コードページ)を指定する。
-
HTTP ヘッダ
Content-Type: text/html; charset=Shift_JIS -
meta タグ
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-
@IT:Javaの文字化け対策FAQ(1)
http://www.atmarkit.co.jp/fjava/rensai3/mojibake01/mojibake01.html- 質問1:Web ブラウザが文字コードを判定する基準は何ですか?
HTTP ヘッダか、meta タグにエンコーディングを指定 - 質問2:page ディレクティブで文字コードを正しく指定する方法は?
CGI 毎、HTML を出力する際に指定する方法が存在する。
- 質問1:Web ブラウザが文字コードを判定する基準は何ですか?
補足(現在の書き方と優先順位): HTML5 では 短い形式が使える。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <!-- ← HTML5 の書き方。先頭 1024 バイト以内に置く -->判定の優先順位(強い順):
① HTTP ヘッダの Content-Type: charset=… ← 最も強い ② BOM(バイト オーダー マーク) ③ <meta charset="…"> ④ ブラウザの推測 / 既定値① が ③ を上書きするため、
HTML に UTF-8 と書いても、サーバが別の charset を返せば化ける。
ここが実務でよく詰まる点である。現在の指針:
・【UTF-8 以外を使わない】 HTML Standard は UTF-8 を要求している ・HTTP ヘッダと meta の両方を UTF-8 に揃える ・meta charset は【head の先頭付近】に置く (1024 バイトを過ぎるとブラウザが再解析する) ・BOM は付けない(UTF-8 では不要。付けても害は少ないが不要)ASP.NET Core では既定で UTF-8 が使われるため、
明示的に変更していなければ問題は起きない。
ヘッダ部分の記述を DOM が理解して自動的にエンコード・デコードします。
<?xml version="1.0" encoding="Shift_JIS"?>移行メモ(原文の XML 宣言に閉じ記号の誤りがある): 原文は
<?xml version="1.0" encoding="Shift_JIS">と書いているが、
XML 宣言は?>で閉じる必要がある
(上のコードでは修正済み)。補足: XML では宣言と実体が食い違うと、パーサがエラーにする
(HTML のように黙って推測しない)。これは良い性質である。・encoding を省略した場合、【UTF-8 と見なされる】 ・BOM があれば、BOM が優先される ・宣言と実体が違えば、パース エラー.NET で XML を書き出す際、
XmlWriterSettings.Encodingと実際の書き込み先を揃える。var settings = new XmlWriterSettings { Encoding = new UTF8Encoding(false) }; using var writer = XmlWriter.Create("out.xml", settings);
new UTF8Encoding(false)のfalseは BOM を付けない指定である。
Encoding.UTF8は BOM 付きなので、
意図せず BOM が入って相手システムが読めなくなる事故が起きる。
-
概要
- URI において使用できない文字を使う際に行われるエンコード(エスケープ)を行う。
- RFC3986 の Section 2.1 で定義されている。
-
利用シーン
- Query String 経由でデータを受け渡す場合にも使用する。
-
参考
補足(.NET のエンコード API の使い分け): URL エンコードには
微妙に仕様の違う API が複数あるため、混同すると事故になる。
API 空白の扱い 用途 Uri.EscapeDataString%20RFC 3986 準拠。これを使う Uri.EscapeUriString%20廃止済み(Obsolete)。使わない HttpUtility.UrlEncode+application/x-www-form-urlencoded(フォーム)WebUtility.UrlEncode+同上( System.Net側)Uri.EscapeDataString("あ い"); // "%E3%81%82%20%E3%81%84" HttpUtility.UrlEncode("あ い"); // "%e3%81%82+%e3%81%84"
+を空白と解釈するのはフォーム送信の規則であり、
**URL のパス部分では+は「プラス記号そのもの」**である。
パスにHttpUtility.UrlEncodeを使うと、
空白が+になって相手に別の文字列として届く。【使い分け】 URL のパス・クエリの【値】 → Uri.EscapeDataString フォームの POST ボディ → HttpUtility.UrlEncode文字コードにも注意する。
URL エンコードはバイト列を %XX にするだけなので、
元のバイト列が UTF-8 か CP932 かで結果が変わる。
現在は UTF-8 が既定(RFC 3986 が推奨)だが、
古いシステムは CP932 で送ってくることがある。
-
概要
- Byte データと文字列の相互変換を行う。
-
利用シーン
- Byte データを Text ベースのプロトコル(SMTP, HTTP 等)に乗せる場合に使用する。
-
参考
- Base64 - Wikipedia
https://ja.wikipedia.org/wiki/Base64
- Base64 - Wikipedia
補足(Base64 の実際): Base64 は暗号化ではない——
誤解が多いので明記しておく。誰でも復元できる。string s = Convert.ToBase64String(Encoding.UTF8.GetBytes("秘密")); // "56eY5a+G" ← 単に読みにくいだけで、秘匿性はないサイズが約 4/3 に増える点も重要である
(3 バイト → 4 文字)。大きなデータには向かない。URL で使う場合は「Base64 URL セーフ」が要る。
【標準の Base64】 + / = ← URL で意味を持つ文字が入る 【Base64 URL セーフ】 - _ ← + → -、/ → _、= は除去JWT やトークン系はすべて URL セーフである。
// .NET 9 以降は標準 API がある var s = System.Buffers.Text.Base64Url.EncodeToString(bytes); // それ以前は自前で置換する var s = Convert.ToBase64String(bytes) .Replace('+', '-').Replace('/', '_').TrimEnd('=');性能が要る場面では
Convert.TryToBase64Charsを使うと
中間の文字列割り当てを避けられる。
CSV ファイルを扱い際は、以下のことに気を付ける。
Excel にて文字化けやエラーが発生せず読み込める CSV ファイルは、
以下の 2 種類のエンコードのファイルである。
- BOM 付き UTF-8
- 各言語(国)の ANSI コード
各言語(国)の ANSI コード(一例)
| # | 言語 | 文字セット名 | codepage |
|---|---|---|---|
| 1 | 日本語 | Shift-JIS | 932 |
| 2 | 英語(米国) | Windows-1252 | 1252 |
| 3 | 英語(英国) | Windows-1252 | 1252 |
| 4 | フランス語(フランス) | Windows-1252 | 1252 |
| 5 | スペイン語(スペイン) | Windows-1252 | 1252 |
| 6 | 繁体字中国語 | big5 | 950 |
| 7 | 簡体字中国語 | gb2312 | 936 |
| 8 | 韓国語 | ks_c_5601-1987 | 949 |
Excel 上で CSV 形式で保存すると、ANSI コードで保存される。
補足(CSV と Excel の現況): 原文の「BOM 付き UTF-8」という指摘が
最も重要な実務知識で、現在も変わらない。・BOM なし UTF-8 の CSV を Excel でダブルクリックすると → 【CP932 と誤認して文字化けする】 ・BOM 付き UTF-8 なら → 正しく UTF-8 と認識される// Web アプリから CSV をダウンロードさせる際 var bom = new UTF8Encoding(true).GetPreamble(); // EF BB BF await stream.WriteAsync(bom); await using var writer = new StreamWriter(stream, new UTF8Encoding(false));XML では BOM を付けないのが無難、CSV では BOM を付ける——
という逆の指針になる点に注意する。現況の補足:
項目 現在 Excel の「保存」 既定は今も ANSI(CP932)。「CSV UTF-8」形式が別に選べる Microsoft 365 **「CSV UTF-8 (コンマ区切り)」**が選択肢にある(BOM 付き) 区切り文字 地域設定に依存(欧州では ;になる国がある)改行を含むセル "で囲む。RFC 4180そもそも CSV を避けられるなら避けるのが最善である。
代替 利点 .xlsxを直接生成(ClosedXML 等)文字コードの問題が消える。書式も付けられる JSON 構造を持てる。UTF-8 が前提 TSV 区切り文字の衝突が起きにくい CSV は**「区切り文字」「引用符」「改行」「文字コード」の 4 つが
すべて曖昧**という、交換形式として弱い仕様である。
帳票出力 で触れた通り、
利用者が Excel で加工する前提なら.xlsxを直接吐く方が確実である。
-
文字化けしないようにするには
https://www.tohoho-web.com/wwwxx005.htm -
Oracleトラブル対策の基礎知識(6):
文字化けに関するトラブルに強くなる【実践編】 (1-4) - @IT
https://atmarkit.itmedia.co.jp/ait/articles/0903/04/news115.html
- .NET での文字エンコード
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/character-encoding-introduction - コード ページ識別子
https://learn.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers - System.Text.Encoding クラス
https://learn.microsoft.com/ja-jp/dotnet/api/system.text.encoding - .NET Core での既定のエンコーディングの変更
https://learn.microsoft.com/ja-jp/dotnet/api/system.text.codepagesencodingprovider
Tags: 移行, .NET開発, 国際化対応, 文字コード
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。