.NET アプリにおいて Encoding.GetEncoding メソッドで Shift_JIS のエンコーディングを取得しようとすると、以下の画像のように ArgumentException 例外がスローされます。

これは、.NET では特定の OS に依存する機能はサポートされてないので、Shift_JIS に限らず Windows OS のコードページの中の特定の locale のエンコーディングはデフォルトでは使えないということのようです。(注: .NET Framework ではデフォルトで Windows コードページの大多数のエンコーディングが使えます)
サポートされているエンコーディングは Encoding.GetEncodings メソッドで取得できます。.NET 8.0 の場合、自分の環境で試すと以下の 7 種類になっていました。
-
ASCII (code page 20127)
-
UTF-8 (code page 65001)
-
UTF-16LE (code page 1200)
-
UTF-16BE (code page 1201)
-
UTF-32LE (code page 12000)
-
UTF-32BE (code page 12001)
-
ISO-8859-1 (code page 28591)
UTF-7 も含まれるというMicrosoft のドキュメントを目にしましたが "The UTF-7 encoding is insecure and should not be used." ということで除外されたようです。
では、.NET アプリで上の一覧にないエンコーディングを Encoding.GetEncoding メソッドで取得して使うにはどうするかですが、それについては Microsoft のドキュメント「EncodingProvider クラス」に説明があります。それを参考に以下に Shift_JIS を使う場合の例を書きます。
(1) プロバイダクラスを定義
抽象クラス EncodingProvider を継承したプロバイダクラスを定義します。この例では、プロバイダクラスの名前を ShiftJisEncodingProvider とします。
ShiftJisEncodingProvider クラスで、 継承した抽象クラス EncodingProvider の抽象メソッド GetEncoding(Int32) と GetEncoding(String) を override し、Shift_JIS エンコーディングを返すようにします。
Shift_JIS エンコーディングは CodePagesEncodingProvider クラスのインスタンスから取得します。
ShiftJisEncodingProvider クラスのコード例は以下の通りです。
using System.Text;
public class ShiftJisEncodingProvider : EncodingProvider
{
public override Encoding? GetEncoding(int codepage)
{
var provider = CodePagesEncodingProvider.Instance;
if (codepage == 932)
{
return provider.GetEncoding(932);
}
return null;
}
public override Encoding? GetEncoding(string name)
{
var provider = CodePagesEncodingProvider.Instance;
if (name.Equals("shift_jis", StringComparison.CurrentCultureIgnoreCase))
{
return provider.GetEncoding("shift_jis");
}
return null;
}
}
(2) ShiftJisEncodingProvider の登録
ShiftJisEncodingProvider のインスタンスを Encoding.RegisterProvider メソッド に渡して、.NET アプリで Shift_JIS エンコーディングを取得できるようにします。
(3) Shift_JIS エンコーディングの取得
.NET アプリでは Encoding.GetEncoding メソッドを使って Shift_JIS エンコーディングを取得します。ステップ (2) と (3) のコード例は以下の通りです。コメントの結果に示すように期待通り Shift_JIS エンコーディングが取得できています。
using System.Text;
namespace ConsoleApp4
{
internal class Program
{
static void Main(string[] args)
{
var provider = new ShiftJisEncodingProvider();
Encoding.RegisterProvider(provider);
var sjis = Encoding.GetEncoding("shift_jis");
Console.WriteLine($"{sjis.EncodingName}\t{sjis.CodePage}\t{sjis.WebName}");
var str = "123abcあいう";
Console.Write($"{str}: ");
byte[] bytes = sjis.GetBytes(str);
foreach (byte b in bytes)
{
Console.Write($"[{b:x2}]");
}
}
}
}
// 結果:
// Japanese (Shift-JIS) 932 shift_jis
// 123abcあいう: [31][32][33][61][62][63][82][a0][82][a2][82][a4]
上で述べたようなカスタムプロバイダクラスを定義しなくても Windows コードページのエンコーディングを簡単に全部使えるようにする方法もあります。
その方法は、Microsoft のドキュメント「CodePagesEncodingProvider クラス」に説明があります。
-
CodePagesEncodingProvider.Instance 静的プロパティから CodePagesEncodingProvider オブジェクトを取得します。
-
CodePagesEncodingProvider オブジェクトを Encoding.RegisterProvider メソッドに渡します。
コード例は以下の通りで一行で済みます。必要ないエンコーディングまで使えるようにすることで何か予期せぬ副作用が出るかもしれないという可能性は否定しきれませんが、こちらのが本筋かもしれません。
using System.Text;
namespace ConsoleApp4
{
internal class Program
{
static void Main(string[] args)
{
// 以下の一行で OK
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var sjis2 = Encoding.GetEncoding("shift_jis");
Console.WriteLine($"{sjis2.EncodingName}\t{sjis2.CodePage}\t{sjis2.WebName}");
Console.Write($"{str}: ");
byte[] bytes2 = sjis2.GetBytes(str);
foreach (byte b in bytes2)
{
Console.Write($"[{b:x2}]");
}
Console.WriteLine("\n\nサポートしているすべてのエンコーディングを取得する");
EncodingInfo[] eis = Encoding.GetEncodings();
foreach (EncodingInfo ei in eis)
{
Console.WriteLine($"{ei.DisplayName}\t{ei.CodePage}\t{ei.Name}");
}
}
}
}
/* 結果
Japanese (Shift-JIS) 932 shift_jis
123abcあいう: [31][32][33][61][62][63][82][a0][82][a2][82][a4]
サポートしているすべてのエンコーディングを取得する
Japanese (Shift-JIS) 932 shift_jis
Portuguese (DOS) 860 IBM860
Icelandic (DOS) 861 ibm861
IBM EBCDIC (Cyrillic Russian) 20880 IBM880
Hebrew (DOS) 862 DOS-862
French Canadian (DOS) 863 IBM863
Chinese Simplified (GB2312) 936 gb2312
Arabic (864) 864 IBM864
Nordic (DOS) 865 IBM865
Cyrillic (DOS) 866 cp866
Cyrillic (KOI8-U) 21866 koi8-u
IBM EBCDIC (US-Canada) 37 IBM037
Greek, Modern (DOS) 869 ibm869
IBM EBCDIC (International) 500 IBM500
Icelandic (Mac) 10079 x-mac-icelandic
IBM EBCDIC (US-Canada-Euro) 1140 IBM01140
IBM EBCDIC (Germany-Euro) 1141 IBM01141
IBM EBCDIC (Denmark-Norway-Euro) 1142 IBM01142
IBM EBCDIC (Germany) 20273 IBM273
IBM EBCDIC (Finland-Sweden-Euro) 1143 IBM01143
IBM EBCDIC (Italy-Euro) 1144 IBM01144
IBM EBCDIC (Spain-Euro) 1145 IBM01145
Central European (Windows) 1250 windows-1250
IBM EBCDIC (UK-Euro) 1146 IBM01146
Cyrillic (Windows) 1251 windows-1251
IBM EBCDIC (France-Euro) 1147 IBM01147
Western European (Mac) 10000 macintosh
Western European (Windows) 1252 windows-1252
Arabic (DOS) 720 DOS-720
IBM EBCDIC (Denmark-Norway) 20277 IBM277
IBM EBCDIC (International-Euro) 1148 IBM01148
Japanese (Mac) 10001 x-mac-japanese
Greek (Windows) 1253 windows-1253
OEM United States 437 IBM437
IBM EBCDIC (Finland-Sweden) 20278 IBM278
IBM EBCDIC (Icelandic-Euro) 1149 IBM01149
Chinese Traditional (Mac) 10002 x-mac-chinesetrad
Turkish (Windows) 1254 windows-1254
Hebrew (Windows) 1255 windows-1255
Korean (Johab) 1361 Johab
Arabic (Windows) 1256 windows-1256
Arabic (Mac) 10004 x-mac-arabic
Baltic (Windows) 1257 windows-1257
Hebrew (Mac) 10005 x-mac-hebrew
Vietnamese (Windows) 1258 windows-1258
Greek (Mac) 10006 x-mac-greek
Cyrillic (Mac) 10007 x-mac-cyrillic
IBM Latin-1 20924 IBM00924
Central European (ISO) 28592 iso-8859-2
Latin 3 (ISO) 28593 iso-8859-3
Baltic (ISO) 28594 iso-8859-4
Cyrillic (ISO) 28595 iso-8859-5
Arabic (ISO) 28596 iso-8859-6
IBM EBCDIC (Multilingual Latin-2) 870 IBM870
Greek (ISO) 28597 iso-8859-7
Hebrew (ISO-Visual) 28598 iso-8859-8
Turkish (ISO) 28599 iso-8859-9
Turkish (Mac) 10081 x-mac-turkish
Croatian (Mac) 10082 x-mac-croatian
Thai (Windows) 874 windows-874
IBM EBCDIC (Greek Modern) 875 cp875
IBM EBCDIC (Arabic) 20420 IBM420
Korean 949 ks_c_5601-1987
IBM EBCDIC (Greek) 20423 IBM423
IBM EBCDIC (Hebrew) 20424 IBM424
IBM EBCDIC (Italy) 20280 IBM280
IBM Latin-1 1047 IBM01047
IBM EBCDIC (Spain) 20284 IBM284
IBM EBCDIC (UK) 20285 IBM285
Romanian (Mac) 10010 x-mac-romanian
Japanese (JIS 0208-1990 and 0212-1990) 20932 EUC-JP
Ukrainian (Mac) 10017 x-mac-ukrainian
Europa 29001 x-Europa
Greek (DOS) 737 ibm737
Western European (IA5) 20105 x-IA5
Chinese Traditional (Big5) 950 big5
Chinese Simplified (GB2312-80) 20936 x-cp20936
German (IA5) 20106 x-IA5-German
Swedish (IA5) 20107 x-IA5-Swedish
Norwegian (IA5) 20108 x-IA5-Norwegian
Cyrillic (KOI8-R) 20866 koi8-r
Baltic (DOS) 775 ibm775
Estonian (ISO) 28603 iso-8859-13
IBM EBCDIC (Japanese katakana) 20290 IBM290
Latin 9 (ISO) 28605 iso-8859-15
Chinese Traditional (CNS) 20000 x-Chinese-CNS
Arabic (ASMO 708) 708 ASMO-708
IBM EBCDIC (France) 20297 IBM297
Thai (Mac) 10021 x-mac-thai
TCA Taiwan 20001 x-cp20001
IBM EBCDIC (Turkish) 20905 IBM905
Chinese Traditional (Eten) 20002 x-Chinese-Eten
IBM EBCDIC (Korean Extended) 20833 x-ebcdic-koreanextended
IBM5550 Taiwan 20003 x-cp20003
TeleText Taiwan 20004 x-cp20004
Wang Taiwan 20005 x-cp20005
Western European (DOS) 850 ibm850
IBM EBCDIC (Thai) 20838 IBM-Thai
Central European (DOS) 852 ibm852
IBM EBCDIC (Icelandic) 20871 IBM871
Central European (Mac) 10029 x-mac-ce
OEM Cyrillic 855 IBM855
IBM EBCDIC (Cyrillic Serbian-Bulgarian) 21025 cp1025
Korean Wansung 20949 x-cp20949
Turkish (DOS) 857 ibm857
OEM Multilingual Latin I 858 IBM00858
T.61 20261 x-cp20261
IBM EBCDIC (Turkish Latin-5) 1026 IBM1026
ISO-6937 20269 x-cp20269
Unicode 1200 utf-16
Unicode (Big-Endian) 1201 utf-16BE
Unicode (UTF-32) 12000 utf-32
Unicode (UTF-32 Big-Endian) 12001 utf-32BE
US-ASCII 20127 us-ascii
Western European (ISO) 28591 iso-8859-1
Unicode (UTF-8) 65001 utf-8
*/