はじめに
今回はエンディアンの変換についてお話したいと思います。
エンディアン(英: endianness)は、複数のバイトなどを並べる順序の種類である。一般的な用語による表現ではバイトオーダ(英: byte order)、ないしそれを一部訳して日本語ではバイト順とも言う。
概要
エンディアンには色々と種類があるようですが、ビッグエンディアンとリトルエンディアンが有名なようです。
例えば、十六進法で表現すると1234ABCDという1ワードが4バイトのデータを、バイト毎に上位側(通常左側)から「12 34 AB CD」のように並べる順序はビッグエンディアン[1]、下位側(通常右側)から「CD AB 34 12」のように並べる順序はリトルエンディアン[2]である。
これらの違いは以下のサイトが体感的で分かりやすかったです。
16進数変換(リトルエンディアン変換)ツール

リトルエンディアンかどうか調べる
エンディアンはCPU
によって決まっていて、C#
ではBitConverter.IsLittleEndian
を利用することでリトルエンディアンかどうかを調べることができます。
https://docs.microsoft.com/ja-jp/dotnet/api/system.bitconverter.islittleendian?view=net-6.0
// True
Console.WriteLine(BitConverter.IsLittleEndian);
エンディアンを変更する
基本的にbyte[]
を逆順に並べるだけで良いです。
// 10進数 : 1, 35, 69, 103, 137, 171, 205, 239 var bytes = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}; // 10進数 : 239, 205, 171, 137, 103, 69, 35, 1 Console.WriteLine(string.Join(",", bytes.Reverse().ToArray()));
// 10進数 : 1, 35, 69, 103, 137, 171, 205, 239 var bytes = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; Array.Reverse(bytes); // 10進数 : 239, 205, 171, 137, 103, 69, 35, 1 Console.WriteLine(string.Join(",", bytes));
BinaryReader/Writerでの仕様
C#
にはバイトの読み書きを行うBinaryReader
とBinaryWriter
というクラスが用意されていますが、どちらもリトルエンディアンを利用しています。
BinaryReader クラス (System.IO) | Microsoft Docs
BinaryWriter クラス (System.IO) | Microsoft Docs
またビッグエンディアンに対応しているBinaryReader/Writer
は実装されていないようなので、自前で実装する必要があるようです。
ただエンディアンを利用した読み書きとしてBinaryPrimitives
というstatic
クラスが存在します。
特定のエンディアンを持つプリミティブとしてバイトを読み取ります。
伝統的なエンディアン変換
何バイト単位でバイトの並びを逆にするかは、型によって異なるようです。例えばint
は4byte
ですね。
sizeof 演算子 - C# リファレンス | Microsoft Docs
まずはint
を伝統的なビットシフトによって実装してみます。
int a = 24225748; // 212, 167, 113, 1 Console.WriteLine(string.Join(",", BitConverter.GetBytes(a))); // ビットシフトを利用してエンディアン変換 int b = (int)( ((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24) ); // 1, 113, 167, 212 Console.WriteLine(string.Join(",", BitConverter.GetBytes(b)));
初見だとビットシフトが訳わからないかと思いますが、図にしてみると分かりやすいかもしれません。

ほかの型でも同じようにしてあげればOKです。
また仕組みを理解するためにはビットシフトをしてもよいですが、ぶっちゃけBinaryPrimitives
を利用した方がよいとは思います。