2010-11-14 6 views
42

Я думал. У .NET был какой-то простой метод преобразования, который можно использовать для преобразования int в массив байтов? Я сделал быстрый поиск, и все решения бит маскируют/сдвигают один байт за раз, например «хорошие дни». Не существует ли метода ToByteArray()?Int to byte array

ответ

69
byte[] bytes = BitConverter.GetBytes(i); 

хотя примечание также, что вы может хотите проверить BitConverter.IsLittleEndian, чтобы увидеть, какой путь вокруг этого будет появляться!

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

+2

+1: Для ясности я бы заменил в «[...] в том порядке, в котором вы ожидаете их» с «big-endian». – Ani

+0

Почему 'BitConverter.GetBytes (250)' return '[250,0,0,0]', а не '[250]'? 'Byte.MaxValue == 255', правильно? – 2017-05-14 23:20:06

+0

@Tobi, потому что вы вызываете GetBytes (int) - так: 4 байта, а ваш процессор малоподвижный. В методе GetBytes (byte) не было бы никакой цели. –

28

Ответ Марка, конечно, правильный ответ. Но поскольку он упомянул операторы сдвига и небезопасный код в качестве альтернативы. Я хотел бы поделиться менее распространенной альтернативой. Использование структуры с макетом 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); 

Конечно неизменность полиция не может быть возбужден о последнем Possiblity :)

+0

+ 1: Это хороший подход. Если вы беспокоитесь о полиции неизменности, вы можете сделать частные поля и разоблачить их с помощью свойств только для получения. – Ani

+0

@Ani, Спасибо, это хорошая идея сделать члены 'byte' частными и создать свойства get-only. –

+0

Утверждение (ы) 'Byte1 = Byte2 = Byte3 = Byte4 = 0;' являются избыточными, поскольку последующее присваивание значения перезаписывает их. Это как раз псевдонимы, которые приводят в порядок гайки писателей-оптимизаторов компилятора. Объединение элегантно, так как оно сжимает несколько записей в один канал через канал памяти. Использование структуры также позволяет избежать распределения массива для чрезвычайно частых случаев. – Pekka

2

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

0

Большинство ответов здесь являются «UnSafe» или нет LittleEndian безопасности. BitConverter не LittleEndian безопасно. Так здание на примере в here (см пост по PZahra) Я сделал LittleEndian безопасную версию, просто читая байтовый массив в обратном порядке, когда BitConverter.IsLittleEndian == истинный

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 

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

+0

Он не начинается с int, однако. Не говоря уже о том, что гораздо логичнее делать эту проверку на _read_, поэтому вы уверены, что ваши данные похожи в массиве. – Nyerguds