Int в байтовый массив - PullRequest
       9

Int в байтовый массив

54 голосов
/ 14 ноября 2010

Я думал, что .net имеет какой-то простой метод преобразования, используемый для преобразования int в байтовый массив?Я сделал быстрый поиск, и все решения маскируются / сдвигаются по одному байту за раз, как в "хорошие старые дни".Нет ли где-нибудь метода ToByteArray ()?

Ответы [ 5 ]

88 голосов
/ 14 ноября 2010
byte[] bytes = BitConverter.GetBytes(i);

хотя учтите также, что вы могли бы захотеть проверить BitConverter.IsLittleEndian, чтобы увидеть, какой путь появится вокруг!* неоднократно вы можете захотеть избежать всех этих недолговечных распределений массивов, написав его самостоятельно с помощью операций сдвига (>> / <<) или с помощью кода unsafe.Операции сдвига также имеют то преимущество, что они не подвержены влиянию порядка действий вашей платформы;вы всегда получаете байты в том порядке, в котором ожидаете их.

30 голосов
/ 14 ноября 2010

Марк ответ, конечно, правильный ответ. Но так как он упомянул операторы сдвига и небезопасный код в качестве альтернативы. Я хотел бы поделиться менее распространенной альтернативой. Использование структуры с макетом Explicit. Это в принципе похоже на C / C ++ union.

Здесь приведен пример структуры, которую можно использовать для получения байтов компонентов типа данных Int32, и приятно то, что это два способа, вы можете манипулировать значениями байтов и видеть влияние на 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);

Конечно, полиция неизменности не может быть взволнована последней возможностью:)

2 голосов
/ 14 ноября 2010

Это может быть OT, но если вы сериализуете много примитивных типов или структур POD, Буферы протокола Google для .Net могут быть вам полезны.Это решает проблему с порядком байтов @Marc, поднятую выше, среди других полезных функций.

1 голос
/ 15 марта 2018

Если вы пришли сюда из Google

Альтернативный ответ на старый вопрос относится к библиотеке Джона Скита, в которой есть инструменты, позволяющие записывать примитивные типы данных непосредственно в байт [] с помощьюСмещение индекса.Намного лучше, чем BitConverter, если вам нужна производительность.

Более старая тема, обсуждающая эту проблему здесь

Библиотеки Джона Скита здесь

Просто скачайте исходный код и посмотрите на пространство имен MiscUtil.Conversion.EndianBitConverter.cs обрабатывает все за вас.

Я предполагаю, что Microsoft не реализовала это, потому что .NET Framework - это код DeFacto Safe.Но кажется смешным, что тысячи людей вынуждены делать сдвиги или ходить в стороннюю библиотеку, чтобы удовлетворить такую ​​основную потребность.

0 голосов
/ 11 ноября 2014

Большинство ответов здесь либо «Небезопасны», либо не безопасны для LittleEndian. BitConverter не является безопасным для LittleEndian. Поэтому, опираясь на пример в здесь (см. Сообщение PZahra), я сделал безопасную версию LittleEndian, просто прочитав байтовый массив в обратном порядке, когда 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

, который является точным гексом, который вошел в массив байтов.

...