web-dev-qa-db-ja.com

Int toバイト配列

.netには、intをバイト配列に変換するために使用する何らかの簡単な変換方法があると思いましたか?私はクイック検索を行いましたが、すべてのソリューションは、「古き良き時代」のように、一度に1バイトずつビットマスキング/シフトしています。 ToByteArray()メソッドはどこにもありませんか?

54
Brady Moritz
byte[] bytes = BitConverter.GetBytes(i);

ただし、mightを確認したいことにも注意してくださいBitConverter.IsLittleEndianそれがどの方向に現れるかを見るために!

これを行っている場合繰り返しいずれかのシフト操作(>>/<<)、またはunsafeコードを使用します。シフト操作()は、プラットフォームのエンディアンの影響を受けないという利点があります。 you always期待する順序でバイトを取得します。

89
Marc Gravell

マークの答えはもちろん正しい答えです。しかし、彼は代替としてシフト演算子と安全でないコードに言及しました。あまり一般的ではない代替案を共有したいと思います。 Explicitレイアウトで構造体を使用します。これは、原則としてC/C++ unionと似ています。

Int32データ型のコンポーネントバイトを取得するために使用できる構造体の例を次に示します。ナイスなことは、2つの方法であり、バイト値を操作してIntに対する効果を確認できることです。

  using System.Runtime.InteropServices;

  [StructLayout(LayoutKind.Explicit)]
  struct Int32Converter
  {
    [FieldOffset(0)] public int Value;
    [FieldOffset(0)] public byte Byte1;
    [FieldOffset(1)] public byte Byte2;
    [FieldOffset(2)] public byte Byte3;
    [FieldOffset(3)] public byte Byte4;

    public Int32Converter(int value)
    {
      Byte1 = Byte2 = Byte3 = Byte4 = 0;
      Value = value;
    }

    public static implicit operator Int32(Int32Converter value)
    {
      return value.Value;
    }

    public static implicit operator Int32Converter(int value)
    {
      return new Int32Converter(value);
    }
  }

上記は次のように使用できるようになりました

 Int32Converter i32 = 256;
 Console.WriteLine(i32.Byte1);
 Console.WriteLine(i32.Byte2);
 Console.WriteLine(i32.Byte3);
 Console.WriteLine(i32.Byte4);

 i32.Byte2 = 2;
 Console.WriteLine(i32.Value);

もちろん、不変性の警察は最後の可能性について興奮していないかもしれません:)

30
Chris Taylor

これはOTかもしれませんが、多くのプリミティブ型またはPOD構造をシリアル化する場合は、 Googleの.Net用プロトコルバッファー が役立つ場合があります。上記で取り上げた@Marcの問題、その他の便利な機能。

2
Steve Townsend

Googleからここに来た場合

古い質問に対する別の答えは、インデックスオフセットを使用してプリミティブデータ型をbyte []に​​直接書き込むためのツールを備えたJohn Skeetのライブラリを参照しています。パフォーマンスが必要な場合は、BitConverterよりはるかに優れています。

ここでこの問題を議論している古いスレッド

ジョン・スキートの図書館はこちら

ソースをダウンロードして、MiscUtil.Conversion名前空間。 EndianBitConverter.csはすべてを処理します。

1
JamesHoux

ここでの回答のほとんどは「UnSafe」またはLittleEndianセーフではありません。BitConverterはLittleEndianセーフではありません。したがって、 here (PZahraの投稿を参照) BitConverter.IsLittleEndian == trueの場合にバイト配列を逆方向に読み取るだけの安全なバージョン

void Main(){    
    Console.WriteLine(BitConverter.IsLittleEndian); 
    byte[] bytes = BitConverter.GetBytes(0xdcbaabcdfffe1608);
    //Console.WriteLine(bytes); 
    string hexStr = ByteArrayToHex(bytes);
    Console.WriteLine(hexStr);
}

public static string ByteArrayToHex(byte[] data) 
{ 
   char[] c = new char[data.Length * 2]; 
   byte b; 
  if(BitConverter.IsLittleEndian)
  {
        //read the byte array in reverse
        for (int y = data.Length -1, x = 0; y >= 0; --y, ++x) 
        { 
            b = ((byte)(data[y] >> 4)); 
            c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
            b = ((byte)(data[y] & 0xF)); 
            c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
        }               
    }
    else
    {
        for (int y = 0, x = 0; y < data.Length; ++y, ++x) 
        { 
            b = ((byte)(data[y] >> 4)); 
            c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
            b = ((byte)(data[y] & 0xF)); 
            c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
        }
    }
    return String.Concat("0x",new string(c));
}

これを返します:

True
0xDCBAABCDFFFE1608

これは、バイト配列に入った正確な16進数です。

0
GregJF