C#での日本語文字の扱い

C#のchar型は2バイト

C#で下記のようなコードを実行してみます。

using System;

class Program
{
    static void Main(string[] args)
    {
        char c = 'あ';
        int i = (int)c;
        Console.WriteLine(c);
        Console.WriteLine("size = " + sizeof(char).ToString());
        Console.WriteLine("code = " + i.ToString("X"));
    }
}

【実行結果】

あ
size = 2
code = 3042

C言語のchar型は1バイトですが、C#のchar型は2バイトであることがわかります。また 'あ' に対応するコードが 3042 であることから UTF-16 であることがわかります。つまり、C#のchar型はC言語でいえばwchar_t型に相当します。

ちなみに、ソースファイルはUTF-8で保存されますが、シフトJISで保存しなおしてビルドしても実行結果は変化しません。あくまで .NETの内部形式としては文字は UTF-16 で扱われます。

バイト列にエンコード

C#のような今どきの言語の場合、文字列データの内部形式がなんであれ、いろいろな文字コードのバイト列にエンコードする手段が提供されています。例えば UTF-8エンコードするには下記のようにします。

using System;
using System.Text;

class Program
{
    static void Main()
    {
        string s = "あいうえお";

        // UTF-8でエンコード
        byte[] buff = Encoding.UTF8.GetBytes(s);

        string hexString = BitConverter.ToString(buff).Replace("-", " ");
        Console.WriteLine(hexString);
    }
}

【実行結果】

E3 81 82 E3 81 84 E3 81 86 E3 81 88 E3 81 8A

'あ' に対応するコードが E38182 であることから、UTF-8だとわかります。

エンコードの行を下記のように変更するとシフトJISエンコードできます。

        // シフトJISでエンコード
        byte[] buff = Encoding.GetEncoding("Shift_JIS").GetBytes(s);

【実行結果】

82 A0 82 A2 82 A4 82 A6 82 A8

'あ' に対応するコードが 82A0 であることから、シフトJISだとわかります。

同様に下記のように変更すると UTF-16エンコードできます。

        // UTF-16でエンコード
        byte[] buff = Encoding.Unicode.GetBytes(s);

【実行結果】

42 30 44 30 46 30 48 30 4A 30

トルエンディアンであることに注意してください。'あ' に対応するコードが 3042 であることから、UTF-16 だとわかります。

バイト列からデコード

逆にUTF-8のバイト列を文字列にデコードするには下記のようにします。

using System;
using System.Text;

class Program
{
    static void Main()
    {
        byte[] buff = {
            0xE3, 0x81, 0x82,
            0xE3, 0x81, 0x84,
            0xE3, 0x81, 0x86,
            0xE3, 0x81, 0x88,
            0xE3, 0x81, 0x8A
        };

        // UTF-8でデコード
        string s = Encoding.UTF8.GetString(buff);

        Console.WriteLine(s);
    }
}

【実行結果】

あいうえお

シフトJISUTF-16のバイト列の場合は下記のようにします。

        // シフトJISでデコード
        string s = Encoding.GetEncoding("Shift_JIS").GetString(buff);
        // UTF-16でデコード
        string s = Encoding.GetEncoding("Shift_JIS").GetString(buff);