C # int to byte [] - PullRequest
       69

C # int to byte []

155 голосов
/ 23 августа 2009

Мне нужно преобразовать int в byte[]. Один из способов сделать это - использовать BitConverter.GetBytes(). Но я не уверен, что это соответствует следующей спецификации:

Целое число со знаком XDR - это 32-разрядное значение, которое кодирует целое число в диапазон [-2147483648,2147483647]. Целое число представлено в два дополнения обозначения. Наиболее и наименее значимые байты 0 и 3 соответственно. Целые числа объявляются следующим образом:

Источник: RFC1014 3.2

Как я могу сделать преобразование int в байты, которое бы удовлетворяло вышеуказанной спецификации?

Ответы [ 7 ]

203 голосов
/ 23 августа 2009

RFC просто пытается сказать, что целое число со знаком является нормальным 4-байтовым целым числом с байтами, упорядоченными в порядке с прямым порядком байтов.

Теперь вы, скорее всего, работаете на машине с прямым порядком байтов, и BitConverter.GetBytes() даст вам byte[] в обратном порядке. Так что вы можете попробовать:

int intValue;
byte[] intBytes = BitConverter.GetBytes(intValue);
Array.Reverse(intBytes);
byte[] result = intBytes;

Чтобы код был максимально переносимым, вы можете сделать это следующим образом:

int intValue;
byte[] intBytes = BitConverter.GetBytes(intValue);
if (BitConverter.IsLittleEndian)
    Array.Reverse(intBytes);
byte[] result = intBytes;
34 голосов
/ 23 августа 2009

Вот еще один способ сделать это: как мы все знаем, 1x байт = 8x бит, а также «обычное» целое число (int32) содержит 32 бита (4 байта). Мы можем использовать оператор >> для сдвига битов вправо (оператор >> не меняет значение.)

int intValue = 566;

byte[] bytes = new byte[4];

bytes[0] = (byte)(intValue >> 24);
bytes[1] = (byte)(intValue >> 16);
bytes[2] = (byte)(intValue >> 8);
bytes[3] = (byte)intValue;

Console.WriteLine("{0} breaks down to : {1} {2} {3} {4}",
    intValue, bytes[0], bytes[1], bytes[2], bytes[3]);
22 голосов
/ 23 августа 2009

BitConverter.GetBytes(int) почти делает то, что вы хотите, за исключением того, что порядок байтов неправильный.

Вы можете использовать метод IPAddress.HostToNetwork , чтобы поменять байты внутри целочисленного значения перед использованием BitConverter.GetBytes или использовать класс EndianBitConverter Джона Скита . Оба метода делают правильные вещи (тм) в отношении переносимости.

int value;
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value));
3 голосов
/ 23 августа 2009

Когда я смотрю на это описание, у меня возникает ощущение, что это целое число xdr является просто «стандартным» целым числом с прямым порядком байтов, но оно выражено самым запутанным образом. Две дополняющие записи лучше известны как U2, и это то, что мы используем в современных процессорах. Порядок байтов указывает, что это нотация big-endian .
Итак, отвечая на ваш вопрос, вы должны инвертировать элементы в вашем массиве (0 <-> 3, 1 <-> 2), так как они закодированы в порядке с прямым порядком байтов. Просто чтобы убедиться, вы должны сначала проверить BitConverter.IsLittleEndian, чтобы увидеть, на какой машине вы работаете.

2 голосов
/ 23 августа 2009

Если вы хотите получить более общую информацию о различных способах представления чисел, включая дополнение к двум, посмотрите:

Дополнение к двум * и Представление подписанного числа в Википедии

0 голосов
/ 03 марта 2018

Почему весь этот код в примерах выше ...

Структура с явным макетом работает в обоих направлениях и не имеет никакого снижения производительности.

Обновление: так как есть вопрос о том, как бороться с порядком байтов, я добавил интерфейс, который иллюстрирует, как это абстрагировать. Другая реализующая структура может иметь дело с противоположным случаем

public interface IIntToByte
{
    Int32 Int { get; set;}

    byte B0 { get; }
    byte B1 { get; }
    byte B2 { get; }
    byte B3 { get; }
}

[StructLayout(LayoutKind.Explicit)]
public struct IntToByteLE : UserQuery.IIntToByte
{
    [FieldOffset(0)]
    public Int32 IntVal;

    [FieldOffset(0)]
    public byte b0;
    [FieldOffset(1)]
    public byte b1;
    [FieldOffset(2)]
    public byte b2;
    [FieldOffset(3)]
    public byte b3;

    public Int32 Int {
        get{ return IntVal; }
        set{ IntVal = value;}
    }

    public byte B0 => b0;
    public byte B1 => b0;
    public byte B2 => b0;
    public byte B3 => b0; 
}
0 голосов
/ 22 февраля 2018
byte[] Take_Byte_Arr_From_Int(Int64 Source_Num)
{
   Int64 Int64_Num = Source_Num;
   byte Byte_Num;
   byte[] Byte_Arr = new byte[8];
   for (int i = 0; i < 8; i++)
   {
      if (Source_Num > 255)
      {
         Int64_Num = Source_Num / 256;
         Byte_Num = (byte)(Source_Num - Int64_Num * 256);
      }
      else
      {
         Byte_Num = (byte)Int64_Num;
         Int64_Num = 0;
      }
      Byte_Arr[i] = Byte_Num;
      Source_Num = Int64_Num;
   }
   return (Byte_Arr);
}
...