概要
ANSI文字列(ここでは純粋なASCIIエンコーディングの文字列ではなくシステム上でANSI版として扱われる文字列。日本語ではShift-JISエンコーディングの文字列)を格納したバイト配列byte[]をstring型へ変換する場合等、ANSI文字列を扱う場合はエンコーディング時のコードページに注意が必要となります。具体的にはANSI文字列をC#のstring型(Unicode)に変換する場合は次の処理が必要となります。
using System.Text;
var buffer = ...
var ansiCodePage = CultureInfo.CurrentCulture.TextInfo.ANSICodePage;
var s = Encoding.GetEncoding(ansiCodePage).GetString(buffer);
なお、P/Invokeではマーシャリングにより自動変換されるので気にする必要はありません。
詳細
ANSIコードページはシステムの言語設定により異なり、Windowsの日本語環境では基本的にShift-JISです。この設定はSystem.Text.CultureInfo.CurrentCulture.TextInfo.ANSICodePageにより取得することができます。
System.Text.EncodingにはASCIIEncodingが存在します。これはANSIエンコーディングの元となる純粋なASCIIエンコーディングであり、先頭の文字はAですがシステム上のANSIエンコーディングとは異なります。ひらがなや漢字等はACSIIエンコーディングに含まれないため、意図的にANSIエンコーディングを指定しないと文字化けが生じます。
また、日本語環境を決め打ちすればGetEncoding("Shift-JIS")やGetEncoding("SJIS")等を使用することもできますが、System.Text.CultureInfo.CurrentCulture.TextInfo.ANSICodePageを使用すれば各言語環境に対応することができます。
サンプルコード
次のサンプルコードはASCIIエンコーディングとShift-JISエンコーディングによる日本語の扱いの違いを示します。
using System; using System.Globalization; using System.Runtime.InteropServices; using System.Text; class Program { private static class NativeMethods { [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)] public static extern void lstrcpynA( [Out] byte[] lpString1, [In] string lpString2, int iMaxLength); } static void Main(string[] args) { var buffer = new byte[256]; NativeMethods.lstrcpynA(buffer, "自分用", buffer.Length); // ASCIIエンコーディングとしてUnicodeへ変換 Console.WriteLine(Encoding.ASCII.GetString(buffer)); // "?????p" // Shift-JISエンコーディングと決め打ちしてとしてUnicodeへ変換 Console.WriteLine(Encoding.GetEncoding("SJIS").GetString(buffer)); // "自分用" // 現在の言語設定のANSIコードページを利用してUnicodeへ変換 var ansiCodePage = CultureInfo.CurrentCulture.TextInfo.ANSICodePage; Console.WriteLine(Encoding.GetEncoding(ansiCodePage).GetString(buffer)); // "自分用" } }
注意する場合の例
- PEファイルからCHAR型(C/C++)を読み込む場合
2021/3/10:この記事は別のブログで投稿した記事を移動したものです。