DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

目的の文字コードに合ったEncodingオブジェクトを取得する

例えばテキストファイルを文字列(String型)として読み込む時、そのテキストファイルの文字コードが何であるかによって、適切なエンコーディング(注)を選択する必要があります。そのエンコーディングを表すのが、Encodingオブジェクトです。適切なEncodingオブジェクトを選択してテキストファイルを読み込まないと、文字化けします。

注:「エンコーディング」とは、どのように文字列をバイト列に変換(エンコード)するかという方法のことです。なおここでは、バイト列を文字列に変換(デコード)する方法を含めて「エンコーディング」と呼ぶことにします。

同様に文字列をテキストファイルに書き込む時も、どのような文字コードで書き込むかによって適切なEncodingオブジェクトを選択する必要があります。

ここでは、目的の文字コードに合ったEncodingオブジェクトを取得する方法について説明します。

なおテキストファイルを読み込む方法は「文字コードを指定してテキストファイルを読み込む」で、テキストファイルに書き込む方法は「文字コードを指定してテキストファイルに書き込む」で説明していますので、ここでは説明しません。

Encoding.GetEncodingメソッドを使う

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のテキストファイルを作成する例を以下に示します。

VB.NET
コードを隠すコードを選択
'シフト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()
C#
コードを隠すコードを選択
//シフト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クラスの静的プロパティには、よく使われる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付き)のテキストファイルを作成する例を以下に示します。

VB.NET
コードを隠すコードを選択
'UTF-8でテキストファイルを作成する
Dim sw As New System.IO.StreamWriter( _
    "C:\test\1.txt", False, System.Text.Encoding.UTF8)
sw.Write("こんにちは。")
sw.Close()
C#
コードを隠すコードを選択
//UTF-8でテキストファイルを作成する
System.IO.StreamWriter sw = new System.IO.StreamWriter(
    @"C:\test\1.txt", false, System.Text.Encoding.UTF8);
sw.Write("こんにちは。");
sw.Close();

Encodingクラスのコンストラクタを呼び出す

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オブジェクトを作成する例を以下に示します。

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//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

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。