DOBON.NET

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

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

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

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

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

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

Encoding.GetEncodingメソッドを使う

Encoding.GetEncodingメソッドを使うことで、指定したエンコーディングのEncodingオブジェクトを取得することができます。この時、エンコーディングのコードページ名かコードページIDを指定する必要があります。コードページ名はString型で、コードページIDはInt32型で指定します。

サポートしているエンコーディングとそのコードページIDおよびコードページ名の一覧がMSDNの「Encoding クラス」にあります。また、サポートしているエンコーディングをすべて取得する方法とその結果の例を、「サポートしているEncodingをすべて取得する」で紹介しています。

日本語に関係したエンコーディングのコードページIDとコードページ名を以下に示します。

表示名コードページIDコードページ名補足
日本語 シフトJIS932shift_jis
shift-jis
x-sjis
sjis
MS_Kanji
など
Shift_JISとは若干異なるが、Shift_JISを扱う場合は通常これを使う
CP932と同じ?
OSが日本語環境の時は、Encoding.Defaultプロパティや、GetEncoding(0)で取得できる
プラットフォームに依存
日本語 (Mac)10001x-mac-japaneseMacJapanese
プラットフォームに依存
日本語 EUC51932euc-jpJIS X 0212をサポートしていないなどEUC-JPとは若干異なるが、EUC-JPを扱う場合は「20932」よりも通常こちらを使う
CP51932と同じ?
日本語 (JIS 0208-1990 および 0212-1990)20932euc-jpMSDNの「Encoding.GetEncodings メソッド」には「20932と51932は同じ」とあるが、若干異なる
JIS X 0212をサポートしている
CP20932に似ているが、3バイト文字はサポートしていない
「GetEncoding("euc-jp")」では、「51932」の方が返される
プラットフォームに依存
日本語 JIS50220iso-2022-jp半角カタカナをサポートするなどISO-2022-JP(JISコード)とは若干異なるが、ISO-2022-JPを扱う場合は通常これを使う
エンコードで半角カタカナが全角カタカナに変換される
「50221」や「50222」でエンコードされた半角カタカナでもデコードできる?
CP50220と同じ?
日本語 JIS(1バイトカタカナ可)(CP50221)50221csISO2022JP半角カタカナ以外は「50220」と同じ?
半角カタカナも半角のまま
エスケープシーケンスを使って半角カタカナをサポート
「50222」でエンコードされた半角カタカナでもデコードできる?
CP50221と同じ?
日本語 JIS(1バイトカタカナ可 - SO/SI)(CP50222)50222iso-2022-jp半角カタカナ以外は「50220」と同じ?
半角カタカナも半角のまま
SO/SIを使って半角カタカナをサポート
「50221」でエンコードされた半角カタカナでもデコードできる?
「GetEncoding("iso-2022-jp")」では、「50220」の方が返される
IBM EBCDIC (日本語カタカナ)20290IBM290IBM CCSID 00290
プラットフォームに依存
UTF-765000utf-7BOMが付いているStreamならば他の形式でもデコードできる?
UTF-865001utf-8Streamに書き込む時にはBOMが付く
BOMが付いているStreamならば他の形式でもデコードできる?
UTF-16 (リトル エンディアン)1200utf-16UTF-16LE
Streamに書き込む時にはBOMが付く
BOMが付いているStreamならば他の形式でもデコードできる?
UTF-16 (ビッグ エンディアン)1201utf-16BE
unicodeFFFE
UTF-16BE
Streamに書き込む時にはBOMが付く
BOMが付いているStreamならば他の形式でもデコードできる?
UTF-32 (リトル エンディアン)12000utf-32UTF-32LE
Streamに書き込む時にはBOMが付く
BOMが付いているStreamならば他の形式でもデコードできる?
UTF-32 (ビッグ エンディアン)12001utf-32BEUTF-32BE
Streamに書き込む時にはBOMが付く
BOMが付いているStreamならば他の形式でもデコードできる?
US-ASCII20127us-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オブジェクトがあらかじめ幾つか用意されています。

このようなプロパティには、以下のようなものがあります。

プロパティ名コードページIDIANA名補足
ASCII20127us-ascii「GetEncoding(20127)」と同じ?
UTF765000utf-7「GetEncoding(65000)」と同じ?
UTF865001utf-8「GetEncoding(65001)」と同じ?
Unicode1200utf-16「GetEncoding(1200)」と同じ?
BigEndianUnicode1201utf-16BE「GetEncoding(1201)」と同じ?
UTF3212000utf-32「GetEncoding(12000)」と同じ?
Default932
(環境によって変わる)
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.ASCIIEncodingUnicode 文字の ASCII 文字エンコーディングを表します。
System.Text.UnicodeEncodingUnicode 文字の UTF-16 エンコーディングを表します。
System.Text.UTF32EncodingUnicode 文字の UTF-32 エンコーディングを表します。(.NET Framework 2.0以降)
System.Text.UTF7EncodingUnicode 文字の UTF-7 エンコーディングを表します。
System.Text.UTF8EncodingUnicode 文字の 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をご利用いただく際は、注意事項をお守りください。
共有する

この記事への評価

この記事へのコメント

この記事に関するコメントを投稿するには、下のボタンをクリックしてください。投稿フォームへ移動します。通常のご質問、ご意見等は掲示板へご投稿ください。