例えばテキストファイルを文字列(String型)として読み込む時、そのテキストファイルの文字コードが何であるかによって、適切なエンコーディング(注)を選択する必要があります。そのエンコーディングを表すのが、Encodingオブジェクトです。適切なEncodingオブジェクトを選択してテキストファイルを読み込まないと、文字化けします。
注:「エンコーディング」とは、どのように文字列をバイト列に変換(エンコード)するかという方法のことです。なおここでは、バイト列を文字列に変換(デコード)する方法を含めて「エンコーディング」と呼ぶことにします。
同様に文字列をテキストファイルに書き込む時も、どのような文字コードで書き込むかによって適切なEncodingオブジェクトを選択する必要があります。
ここでは、目的の文字コードに合ったEncodingオブジェクトを取得する方法について説明します。
なおテキストファイルを読み込む方法は「文字コードを指定してテキストファイルを読み込む」で、テキストファイルに書き込む方法は「文字コードを指定してテキストファイルに書き込む」で説明していますので、ここでは説明しません。
Encoding.GetEncodingメソッドを使うことで、指定したエンコーディングのEncodingオブジェクトを取得することができます。この時、エンコーディングのコードページ名かコードページIDを指定する必要があります。コードページ名はString型で、コードページIDはInt32型で指定します。
サポートしているエンコーディングとそのコードページIDおよびコードページ名の一覧がMSDNの「Encoding クラス」にあります。また、サポートしているエンコーディングをすべて取得する方法とその結果の例を、「サポートしているEncodingをすべて取得する」で紹介しています。
日本語に関係したエンコーディングのコードページIDとコードページ名を以下に示します。
表示名 | コードページID | コードページ名 | 補足 |
---|---|---|---|
日本語 シフトJIS | 932 | shift_jis shift-jis x-sjis sjis MS_Kanji など | Shift_JISとは若干異なるが、Shift_JISを扱う場合は通常これを使う CP932と同じ? OSが日本語環境の時は、Encoding.Defaultプロパティや、GetEncoding(0)で取得できる プラットフォームに依存 |
日本語 (Mac) | 10001 | x-mac-japanese | MacJapanese プラットフォームに依存 |
日本語 EUC | 51932 | euc-jp | JIS X 0212をサポートしていないなどEUC-JPとは若干異なるが、EUC-JPを扱う場合は「20932」よりも通常こちらを使う CP51932と同じ? |
日本語 (JIS 0208-1990 および 0212-1990) | 20932 | euc-jp | MSDNの「Encoding.GetEncodings メソッド」には「20932と51932は同じ」とあるが、若干異なる JIS X 0212をサポートしている CP20932に似ているが、3バイト文字はサポートしていない 「GetEncoding("euc-jp")」では、「51932」の方が返される プラットフォームに依存 |
日本語 JIS | 50220 | iso-2022-jp | 半角カタカナをサポートするなどISO-2022-JP(JISコード)とは若干異なるが、ISO-2022-JPを扱う場合は通常これを使う エンコードで半角カタカナが全角カタカナに変換される 「50221」や「50222」でエンコードされた半角カタカナでもデコードできる? CP50220と同じ? |
日本語 JIS(1バイトカタカナ可)(CP50221) | 50221 | csISO2022JP | 半角カタカナ以外は「50220」と同じ? 半角カタカナも半角のまま エスケープシーケンスを使って半角カタカナをサポート 「50222」でエンコードされた半角カタカナでもデコードできる? CP50221と同じ? |
日本語 JIS(1バイトカタカナ可 - SO/SI)(CP50222) | 50222 | iso-2022-jp | 半角カタカナ以外は「50220」と同じ? 半角カタカナも半角のまま SO/SIを使って半角カタカナをサポート 「50221」でエンコードされた半角カタカナでもデコードできる? 「GetEncoding("iso-2022-jp")」では、「50220」の方が返される |
IBM EBCDIC (日本語カタカナ) | 20290 | IBM290 | IBM CCSID 00290 プラットフォームに依存 |
UTF-7 | 65000 | utf-7 | BOMが付いているStreamならば他の形式でもデコードできる? |
UTF-8 | 65001 | utf-8 | Streamに書き込む時にはBOMが付く BOMが付いているStreamならば他の形式でもデコードできる? |
UTF-16 (リトル エンディアン) | 1200 | utf-16 | UTF-16LE Streamに書き込む時にはBOMが付く BOMが付いているStreamならば他の形式でもデコードできる? |
UTF-16 (ビッグ エンディアン) | 1201 | utf-16BE unicodeFFFE | UTF-16BE Streamに書き込む時にはBOMが付く BOMが付いているStreamならば他の形式でもデコードできる? |
UTF-32 (リトル エンディアン) | 12000 | utf-32 | UTF-32LE Streamに書き込む時にはBOMが付く BOMが付いているStreamならば他の形式でもデコードできる? |
UTF-32 (ビッグ エンディアン) | 12001 | utf-32BE | UTF-32BE Streamに書き込む時にはBOMが付く BOMが付いているStreamならば他の形式でもデコードできる? |
US-ASCII | 20127 | us-ascii ascii |
補足:「プラットフォームに依存」と書かれているものは、.NET Frameworkでネイティブにサポートされている訳ではなく、プラットフォームに依存しています。プラットフォームがサポートしていなければ、使用することができません。例えば日本語シフトJISはWindows 98の米国版などではサポートされていません。サポートされていない場合は、例外ArgumentExceptionがスローされます。
補足:コードページ名は大文字と小文字を区別しないようです。
補足:「文字コード表 - 比較:(日本語 (シフト JIS) - CP932) (日本語 (シフト JIS) - shift_jis)」によると、Shift_JISとCP932の違いは、例えば0x8160の波線文字に現れます。Shift_JISでは「〜」(U+301C、波ダッシュ、wave dash)ですが、CP932では「~」(U+FF5E、全角チルダ、fullwidth tilde)です。この違いは、CP20932とCP51932、ISO-2022-JPとCP50220にも表れます。
シフトJISのテキストファイルを作成する例を以下に示します。
'シフトJISのEncodingオブジェクトを作成する Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding(932) 'または、次のようにすることもできる 'Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("shift_jis") 'シフトJISでテキストファイルを作成する Dim sw As New System.IO.StreamWriter("C:\test\1.txt", False, enc) sw.Write("こんにちは。") sw.Close()
//シフトJISのEncodingオブジェクトを作成する System.Text.Encoding enc = System.Text.Encoding.GetEncoding(932); //または、次のようにすることもできる //System.Text.Encoding enc =System.Text.Encoding.GetEncoding("shift_jis"); //シフトJISでテキストファイルを作成する System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\test\1.txt", false, enc); sw.Write("こんにちは。"); sw.Close();
もっとお手軽な方法として、Encodingクラスの静的プロパティを使用する方法があります。Encodingクラスの静的プロパティには、よく使われるEncodingオブジェクトがあらかじめ幾つか用意されています。
このようなプロパティには、以下のようなものがあります。
プロパティ名 | コードページID | IANA名 | 補足 |
---|---|---|---|
ASCII | 20127 | us-ascii | 「GetEncoding(20127)」と同じ? |
UTF7 | 65000 | utf-7 | 「GetEncoding(65000)」と同じ? |
UTF8 | 65001 | utf-8 | 「GetEncoding(65001)」と同じ? |
Unicode | 1200 | utf-16 | 「GetEncoding(1200)」と同じ? |
BigEndianUnicode | 1201 | utf-16BE | 「GetEncoding(1201)」と同じ? |
UTF32 | 12000 | utf-32 | 「GetEncoding(12000)」と同じ? |
Default | 932 (環境によって変わる) | shift_jis (環境によって変わる) | 環境によって違うエンコーディングを返すので、あまり使用しない方がよい。 |
UTF-8(BOM付き)のテキストファイルを作成する例を以下に示します。
'UTF-8でテキストファイルを作成する Dim sw As New System.IO.StreamWriter( _ "C:\test\1.txt", False, System.Text.Encoding.UTF8) sw.Write("こんにちは。") sw.Close()
//UTF-8でテキストファイルを作成する System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\test\1.txt", false, System.Text.Encoding.UTF8); sw.Write("こんにちは。"); sw.Close();
Encodingクラスは抽象クラスですが、UnicodeとASCIIに関するエンコーディングについては、Encodingクラスから派生した専用のクラスが公開されています。これらのコンストラクタを直接呼び出すことで、Encodingオブジェクトを作成することができます。
このようなクラスには、以下のようなものがあります(MSDNからの抜粋です)。
クラス名 | 説明 |
---|---|
System.Text.ASCIIEncoding | Unicode 文字の ASCII 文字エンコーディングを表します。 |
System.Text.UnicodeEncoding | Unicode 文字の UTF-16 エンコーディングを表します。 |
System.Text.UTF32Encoding | Unicode 文字の UTF-32 エンコーディングを表します。(.NET Framework 2.0以降) |
System.Text.UTF7Encoding | Unicode 文字の UTF-7 エンコーディングを表します。 |
System.Text.UTF8Encoding | Unicode 文字の UTF-8 エンコーディングを表します。 |
この方法には、大きなメリットがあります。それは、Unicode系のエンコーディングでStreamに書き出す時、BOM(バイトオーダーマーク、バイト順マーク、byte order mark)を付けないようにできることです(UTF7Encoding以外)。今まで紹介してきた方法では、必ずBOMが付きます。
また、この方法では、無効な文字やバイトシーケンスがあったときに例外をスローさせるようにすることもできます(ASCIIEncoding、UTF7Encoding以外)。
具体的には、UTF8Encodingでは1番目、UnicodeEncodingとUTF32Encodingでは2番目のパラメータがTrueの時BOMが付加し、Falseの時は付加しません。省略するとFalseになり、付加しません。
UTF8Encodingでは2番目、UnicodeEncodingとUTF32Encodingでは3番目のパラメータがTrueの時、無効な文字やバイトシーケンスがあると例外ArgumentExceptionをスローします(UnicodeEncodingとUTF32Encodingは.NET Framework 2.0以降)。省略するとFalseになり、エラーは出ません。
UnicodeEncodingとUTF32Encodingでは、1番目のパラメータがTrueの時ビッグエンディアンバイト順を使用し、Falseの時はリトルエンディアンバイト順を使用します。省略するとFalseになります。
補足:UTF7Encodingのコンストラクタには多くても1つのパラメータしかなく、これがTrueの時は、「!\|"#$%&*;<>{}[]=@^_`」という文字をBASE64で変換することなく、そのままにします。
この方法で様々なEncodingオブジェクトを作成する例を以下に示します。
'BOMを付けない。また、無効なエンコーディングで例外をスローさせる。 Dim utf8Enc As System.Text.Encoding = _ New System.Text.UTF8Encoding(False, True) Console.WriteLine("{0},{1},{2}", _ utf8Enc.EncodingName, utf8Enc.CodePage, utf8Enc.WebName) 'Unicode (UTF-8),65001,utf-8 'リトルエンディアン。BOMを付けない。例外をスローさせる。 Dim utf16be As System.Text.Encoding = _ New System.Text.UnicodeEncoding(False, False, True) Console.WriteLine("{0},{1},{2}", _ utf16be.EncodingName, utf16be.CodePage, utf16be.WebName) 'Unicode,1200,utf-16 'ビッグエンディアン。BOMを付けない。例外をスローさせる。 Dim utf32le As System.Text.Encoding = _ New System.Text.UTF32Encoding(True, False, True) Console.WriteLine("{0},{1},{2}", _ utf32le.EncodingName, utf32le.CodePage, utf32le.WebName) 'Unicode (UTF-32 ビッグ エンディアン),12001,utf-32BE
//BOMを付けない。また、無効なエンコーディングで例外をスローさせる。 System.Text.Encoding utf8Enc = new System.Text.UTF8Encoding(false, true); Console.WriteLine("{0},{1},{2}", utf8Enc.EncodingName, utf8Enc.CodePage, utf8Enc.WebName); //Unicode (UTF-8),65001,utf-8 //リトルエンディアン。BOMを付けない。例外をスローさせる。 System.Text.Encoding utf16be = new System.Text.UnicodeEncoding(false, false, true); Console.WriteLine("{0},{1},{2}", utf16be.EncodingName, utf16be.CodePage, utf16be.WebName); //Unicode,1200,utf-16 //ビッグエンディアン。BOMを付けない。例外をスローさせる。 System.Text.Encoding utf32le = new System.Text.UTF32Encoding(true, false, true); Console.WriteLine("{0},{1},{2}", utf32le.EncodingName, utf32le.CodePage, utf32le.WebName); //Unicode (UTF-32 ビッグ エンディアン),12001,utf-32BE