C# int в байт[]
мне нужно преобразовать int
до byte[]
один из способов-это использовать BitConverter.GetBytes()
. Но я не уверен, что это соответствует следующей спецификации:
целое число со знаком XDR является 32-разрядным датумом, который кодирует целое число в диапазон [-2147483648,2147483647]. Целое число представлено в виде два дополнения нотации. Наиболее и наименее значимый байт 0 и 3 соответственно. Целые числа объявляются следующим образом:
источник: RFC1014 3.2
как я могу сделать преобразование int в байт, которое удовлетворяло бы приведенной выше спецификации?
7 ответов:
RFC просто пытается сказать, что целое число со знаком является нормальным 4-байтовым целым числом с байтами, упорядоченными по большому концу.
теперь вы, скорее всего, работаете на машине little-endian и
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;
вот еще один способ сделать это: как мы все знаем, 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]);
BitConverter.GetBytes(int)
почти делает то, что вы хотите, за исключением endianness неправильно.можно использовать IPAddress.HostToNetwork метод для замены байтов в целочисленном значении перед использованием
BitConverter.GetBytes
или использовать Джона Скита EndianBitConverter class. Оба метода делают правильную вещь (tm) относительно переносимости.int value; byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value));
когда я смотрю на это описание, у меня есть ощущение, что это целое число xdr-это просто большое "стандартное" целое число, но оно выражено самым запутанным образом. два дополнения нотации лучше знать, как U2, и это то, что мы используем на сегодняшний процессоров. Порядок байтов указывает, что это big-endian нотации.
Итак, отвечая на ваш вопрос, вы должны инвертировать элементы в своем массиве (0 3, 1 2), как они закодированы в little-endian. Просто чтобы убедиться, вы должны сначала проверитьBitConverter.IsLittleEndian
чтобы увидеть, на какой машине вы работаете.
Если вы хотите получить более общую информацию о различных методах представления чисел, включая дополнение двух, посмотрите:
дополнение и Представление Подписанного Числа Википедии
почему весь этот код в примерах выше...
структура с явным макетом действует в обоих направлениях и не имеет хита производительности.
Update: поскольку есть вопрос о том, как бороться с endianness, я добавил интерфейс, который иллюстрирует, как абстрагироваться от этого. Другая реализующая структура может иметь дело с противоположным случаем
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; }
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); }