セージ の メモ書き

メモこそ命の恩人だ

C# - エンディアン/BitConverter クラス

エンディアン

  • Endian : "ガリヴァー旅行記の小人国" が語源。
  • "バイトオーダー" とも呼ぶ。
  • 複数バイトのデータを扱う際のデータの並び方。
  • どのバイトデータから処理すれば良いか把握する必要がある。
    • ネットワークで受信したバイトデータ
    • ファイルから読み込んだバイトデータ
    • 周辺機器から読み込んだバイトデータ
  • 方法は二通り。1byte(8bit) のデータをどちらから扱うか。

例えば、"0x12345678" を処理する場合

方式 順序1→ 順序2→ 順序3→ 順序4
ビッグエンディアン 0x12 0x34 0x56 0x78
トルエンディアン 0x78 0x56 0x34 0x12


BitConverter.IsLittleEndian フィールド

docs.microsoft.com

Debug.WriteLine(BitConverter.IsLittleEndian);
// True
// 自宅PCはリトルエンディアンであることを確認。


BitConverter クラス

  • バイト配列をプリミティブ型に変換できる。(int、string など)
  • 変換時は、エンディアンを意識する必要がある。

プリミティブ型 → バイト配列

docs.microsoft.com

  • BitConverter.GetBytes メソッドを使用する。
  • int、float、double 等々、コンバートできる。

4660(16進数だと"1234") のデータをコンバートしてみる。

void Log(byte[] bytes) 
{
    // 2桁の16進数で記録
    bytes.ToList().ForEach(x => Debug.Write($"{x:X2} "));
    Debug.WriteLine("");
}

byte[] converted;

converted = BitConverter.GetBytes((short)4660);
Log(converted);
// 34 12

converted = BitConverter.GetBytes((int)4660);
Log(converted);
// 34 12 00 00

converted = BitConverter.GetBytes((long)4660);
Log(converted);
// 34 12 00 00 00 00 00 00

// リトルエンディアンでコンバートされた。
// 下位桁から順に並んでいることを確認。
// データ型ごとのサイズでコンバートされてる。

バイト配列 → int

docs.microsoft.com

  • BitConverter.ToInt32 メソッドを使用する。

前述のデータを使って試してみる。

byte[] sample1 = { 0x34, 0x12, 0x00, 0x00 };
Debug.WriteLine(BitConverter.ToInt32(sample1));
// 4660
// リトルエンディアンの環境なので、リトルエンディアンのデータを正しく変換できた。

byte[] sample2 = { 0x00, 0x00, 0x12, 0x34 };
Debug.WriteLine(BitConverter.ToInt32(sample2));
// 873594880
// ビッグエンディアンのデータのため、予想通り 4660 にならないことを確認。
// エンディアンを意識しないと、意図せぬ値となる。
// "バイト配列.Reverse()" して処理すれば、並びを反転できる。

byte[] sample3 = { 0x34, 0x12 };
Debug.WriteLine(BitConverter.ToInt32(sample3));
// 4バイト(int のデータサイズ)でないため、例外発生。
// System.ArgumentOutOfRangeException: 'Specified argument was out of the range of valid values. 



以上