連載
» 2018年10月10日 05時00分 公開

.NET TIPS:Encodingクラスで扱えるエンコーディング名は?[C#/VB]

Encodingクラスのプロパティやメソッドを使って、各種のエンコーディング(特に日本語のエンコーディング)に対応したインスタンスを得る方法を説明する。

[遠藤孝信, 山本康彦,共著]
「.NET TIPS」のインデックス

連載「.NET TIPS」

本稿は2003/04/11に初版公開、2008/07/24に改訂した記事を再改訂し、Visual Studio 2017でコードの動作検証、図版の追加、全般的な構成の変更などを行ったものです。


 ファイルの読み書きなどで文字コードを指定したいときがある。そのために使うEncodingクラス(System.Text名前空間)のインスタンスは、どのようにして取得すればよいだろうか? また、日本語独自のエンコーディングを指定するには、どのようなエンコーディング名が使えるのだろうか? 本稿で整理して紹介する。

POINT Encodingクラスのインスタンスを取得する方法

Encodingクラスのインスタンスを取得する方法 Encodingクラスのインスタンスを取得する方法


 特定のトピックをすぐに知りたいという方は以下のリンクを活用してほしい。

既定で提供されるインスタンス

 一般的なエンコーディングは、Encodingクラスの静的プロパティとして提供されている(次のコード)。新しく構築するシステムなら、その中からUnicode(UTF-8やUTF-16)を使っておけばよい。

// UTF-8
var utf8 = System.Text.Encoding.UTF8;
System.Console.WriteLine(utf8.EncodingName);
// 出力:Unicode (UTF-8)

// UTF-16(リトルエンディアン)
var utf16 = System.Text.Encoding.Unicode;
System.Console.WriteLine(utf16.EncodingName);
// 出力:Unicode

// ASCII(7ビット)
var ascii = System.Text.Encoding.ASCII;
System.Console.WriteLine(ascii.EncodingName);
// 出力:US-ASCII

' UTF-8
Dim utf8 = System.Text.Encoding.UTF8
System.Console.WriteLine(utf8.EncodingName)
' 出力:Unicode (UTF-8)

' UTF-16(リトルエンディアン)
Dim utf16 = System.Text.Encoding.Unicode
System.Console.WriteLine(utf16.EncodingName)
' 出力:Unicode

' ASCII(7ビット)
Dim ascii = System.Text.Encoding.ASCII
System.Console.WriteLine(ascii.EncodingName)
' 出力:US-ASCII

既定で提供されるEncodingインスタンスの例(上:C#、下:VB)

日本語用のインスタンスを取得するには?

 既存のシステムやデータの場合、Unicodeではなく日本語独自のエンコーディングを使っている場合がある。そのようなエンコーディングは上記の静的プロパティでは得られない。

 「TIPS:文字列をシフトJISとしてバイト列に変換するには?」や「TIPS:バイト列を文字列に変換するには?」では、文字列のエンコーディングとしてシフトJISを使用するために、シフトJISをサポートしているEncodingクラス(System.Text名前空間)のインスタンスを次のようにして取得している*1

Encoding sjisEnc = Encoding.GetEncoding("Shift_JIS");

Dim sjisEnc As Encoding = Encoding.GetEncoding("Shift_JIS")

Encodingクラス(System.Text名前空間)のインスタンス作成(上:C#、下:VB)

 ここではパラメーターとして、シフトJISの文字コード体系(キャラクタセット)を表す値を文字列「Shift_JIS」で指定している。シフトJIS以外では、日本語のエンコーディングによく使用されるキャラクタセットとして、次のようなものが指定できる。

  • EUC-JP
  • iso-2022-jp

 GetEncodingメソッドのパラメーターには、キャラクタセットの名前ではなく、それに対応したコードページの値を指定することもできる。例えば、シフトJISに対応したコードページ値は932なので、上のコードは次のように記述しても同等だ。

Encoding sjisEnc = Encoding.GetEncoding(932);

Dim sjisEnc As Encoding = Encoding.GetEncoding(932)

Encoding.GetEncoding("Shift_JIS")と同等の記述(上:C#、下:VB)

 ちなみに、Encodingクラスは既定のインスタンスも提供している(次のコード)。これは、システムのデフォルトのエンコーディングであり、日本語環境ではシフトJISになっている。システムの設定言語が異なればこのエンコーディングも変わってくるので、シフトJISのエンコーディングが欲しいというときにこれを使ってはいけない。

Encoding defaultEnc = Encoding.Default;
Console.WriteLine("{0}, {1}, {2}",  defaultEnc.CodePage,
                    defaultEnc.WebName,  defaultEnc.EncodingName);
// 出力:932, shift_jis, 日本語 (シフト JIS)

Dim defaultEnc As Encoding = Encoding.Default
Console.WriteLine("{0}, {1}, {2}", defaultEnc.CodePage,
                  defaultEnc.WebName, defaultEnc.EncodingName)
' 出力:932, shift_jis, 日本語 (シフト JIS)

EncodingクラスのDefaultプロパティ(上:C#、下:VB)
日本語の環境で実行すると、このようにシフトJISが返ってくる。環境が異なれば、異なるエンコーディングになってしまう。

*1 .NET Core 1.xでは、EncodingクラスのGetEncodingメソッドを呼び出す前に一度だけRegisterProviderメソッドを呼び出しておく必要がある(.NET Core 2.0以降と.NET Frameworkでは不要)。

詳しくは「WinRT/Metro TIPS:シフトJISのEncodingオブジェクトを取得するには?[Windows 10 UWPアプリ開発]」をご覧いただきたい。


エンコーディング名の一覧を取得するには?[.NET 2.0]

 docs.microsoft.comのEncodingクラスのページには、GetEncodingメソッドに渡せるエンコーディング名とコードページ番号の一覧が載っている。しかし、そのページの情報が正しいとは限らない(実際、本稿執筆時点の日本語版では、エンコーディング名の一部が日本語に翻訳されてしまっていて、正しい名前ではなかった)。

 プログラムでエンコーディングの一覧を取得するには、.NET Framework 2.0以降ではEncodingクラスのGetEncodingsメソッドが使える(次のコード)。このメソッドは、EncodingInfoクラスの配列を返してくる。EncodingInfoクラスは、エンコーディング名とコードページのプロパティを持っている。なお、EncodingInfoクラスのGetEncodingメソッドで、そのエンコーディングのEncodingインスタンスが得られる。

using System;
using System.Linq;
using System.Text;

class Program
{
  static void Main(string[] args)
  {
    // 全てのエンコーディング情報を取得
    EncodingInfo[] allEncodings = Encoding.GetEncodings();
    Console.WriteLine("エンコーディング数={0}", allEncodings.Length);
    // 出力:エンコーディング数=140

    // 表示名に「日本語」を含むエンコーディング
    var japaneseEI = allEncodings.Where(ei => ei.DisplayName.Contains("日本語"));
    Console.WriteLine("CodePage\tName\tDisplayName");
    foreach (EncodingInfo ei in japaneseEI)
      Console.WriteLine("{0}\t{1}\t{2}", ei.CodePage, ei.Name, ei.DisplayName);
    // 出力:
    // CodePage        Name    DisplayName
    // 932     shift_jis       日本語 (シフト JIS)
    // 10001   x-mac-japanese  日本語 (Mac)
    // 20290   IBM290  IBM EBCDIC (日本語カタカナ)
    // 20932   EUC-JP  日本語 (JIS 0208-1990 および 0212-1990)
    // 50220   iso-2022-jp     日本語 (JIS)
    // 50221   csISO2022JP     日本語 (JIS 1 バイト カタカナ可)
    // 50222   iso-2022-jp     日本語 (JIS 1 バイト カタカナ可 - SO/SI)
    // 51932   euc-jp  日本語 (EUC)
       
    // 同名のものを指定してEncodingインスタンスを取得すると?
    Console.WriteLine(Encoding.GetEncoding("iso-2022-jp").CodePage);
    // 出力:50220
    Console.WriteLine(Encoding.GetEncoding("EUC-JP").CodePage);
    // 出力:51932
    Console.WriteLine(Encoding.GetEncoding("euc-jp").CodePage);
    // 出力:51932

#if DEBUG
    Console.ReadKey();
#endif
  }
}

Imports System.Text

Module Module1
  Sub Main()
    ' 全てのエンコーディング情報を取得
    Dim allEncodings As EncodingInfo() = Encoding.GetEncodings()
    Console.WriteLine("エンコーディング数={0}", allEncodings.Length)
    ' 出力:エンコーディング数=140

    ' 表示名に「日本語」を含むエンコーディング
    Dim japaneseEI _
      = allEncodings.Where(Function(ei) ei.DisplayName.Contains("日本語"))
    Console.WriteLine("CodePage" + vbTab + "Name" + vbTab + "DisplayName")
    For Each ei As EncodingInfo In japaneseEI
      Console.WriteLine("{0}{1}{2}{3}{4}",
                        ei.CodePage, vbTab, ei.Name, vbTab, ei.DisplayName)
    Next
    ' 出力:
    ' CodePage        Name    DisplayName
    ' 932     shift_jis       日本語 (シフト JIS)
    ' 10001   x-mac-japanese  日本語 (Mac)
    ' 20290   IBM290  IBM EBCDIC (日本語カタカナ)
    ' 20932   EUC-JP  日本語 (JIS 0208-1990 および 0212-1990)
    ' 50220   iso-2022-jp     日本語 (JIS)
    ' 50221   csISO2022JP     日本語 (JIS 1 バイト カタカナ可)
    ' 50222   iso-2022-jp     日本語 (JIS 1 バイト カタカナ可 - SO/SI)
    ' 51932   euc-jp  日本語 (EUC)

    ' 同名のものを指定してEncodingインスタンスを取得すると?
    Console.WriteLine(Encoding.GetEncoding("iso-2022-jp").CodePage)
    ' 出力:50220
    Console.WriteLine(Encoding.GetEncoding("EUC-JP").CodePage)
    ' 出力:51932
    Console.WriteLine(Encoding.GetEncoding("euc-jp").CodePage)
    ' 出力:51932

#If DEBUG Then
    Console.ReadKey()
#End If
  End Sub
End Module

エンコーディングの一覧から日本語独自のものを抜き出すコンソールアプリ(上:C#、下:VB)
このコードはLINQの機能を利用しているため、.NET Framework 3.5以降が必要である。
また、このコードは日本語以外の環境では正しく動作しない(DisplayNameプロパティは実行環境の言語設定に従うため)。
エンコーディング名の同じものが複数ある。コードの最後には、それを指定してEncodingクラスのインスタンスを取得する例も示した(例えばコードページの小さい方が選ばれるというような規則性があるわけではない)。そのようなエンコーディングを厳密に指定するには、コードページを使わねばならない。

 上のサンプルコードでは、日本語用のエンコーディングを抜き出して表示している。全てのエンコーディングを出力する例は、docs.microsoft.comのEncodingInfo.GetEncodingのページに載っている。

エンコーディング名のエイリアス

 実際には、GetEncodingメソッドのパラメーターで指定可能な文字列の元となるデータは、レジストリの次のキー配下で定義されているようだ。

HKEY_CLASSES_ROOT\MIME\Database\Charset

 ここでは、キャラクタセット名に加えて、その別名(Alias)も定義されている。例えば、「Shift_JIS」の別名としては、次のようなものがある。

  • csShiftJIS
  • csWindows31J
  • ms_Kanji
  • shift-jis
  • x-ms-cp932
  • x-sjis

 これらの文字列はどれも、「Shift_JIS」の代わりにGetEncodingメソッドのパラメーターとして使用できる。

カテゴリ:クラスライブラリ 処理対象:文字列
使用ライブラリ:Encodingクラス(System.Text名前空間)
使用ライブラリ:EncodingInfoクラス(System.Text名前空間)
関連TIPS:文字列の長さを取得するには?
関連TIPS:文字列をシフトJISとしてバイト列に変換するには?
関連TIPS:バイト列を文字列に変換するには?
関連TIPS:Visual Studioでコンソール・アプリケーションのデバッグ実行時にコマンド・プロンプトを閉じないようにするには?


更新履歴

【2018/10/10】Visual Studio 2017でコードの動作検証、図版の追加、全般的な構成の変更などを行いました。

【2008/07/24】VB(Visual Basic)のコード例とサンプルプログラムを追加しました。

【2003/04/11】初版公開。


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。