Как мне преобразовать int в массив байтов, а затем обратно? - PullRequest
3 голосов
/ 23 июня 2010

Мне нужно отправить целое число через NetworkStream. Проблема в том, что я могу отправлять только байты. Вот почему мне нужно разделить целое число на четыре байта и отправить их, а на другом конце преобразовать их обратно в целое число.

Пока мне это нужно только в C #. Но для финального проекта мне нужно будет преобразовать четыре байта в int в Lua.

[EDIT] Как насчет Луа?

Ответы [ 8 ]

9 голосов
/ 23 июня 2010

BitConverter - это самый простой способ, но если вы хотите контролировать порядок байтов, вы можете сделать битовое смещение самостоятельно.

int foo = int.MaxValue;
byte lolo = (byte)(foo & 0xff);
byte hilo = (byte)((foo >> 8) & 0xff);
byte lohi = (byte)((foo >> 16) & 0xff);
byte hihi = (byte)(foo >> 24);

Также ... реализация BitConverter использует небезопасные и указатели, нокоротко и просто.

public static unsafe byte[] GetBytes(int value)
{
   byte[] buffer = new byte[4];
   fixed (byte* numRef = buffer)
   {
      *((int*) numRef) = value;
   }
   return buffer;
}
6 голосов
/ 23 июня 2010

Попробуйте

BitConverter.GetBytes ()

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

Просто помните, что порядок байтов в возвращаемом массиве зависит от порядкового номера вашей системы.

EDIT: Что касается части Lua, я не знаю, как конвертировать обратно. Вы всегда можете умножить на 16, чтобы получить одинаковую функциональность побитового сдвига на 4. Это не красиво, и я бы предположил, что есть какая-то библиотека или что-то, что ее реализует. Опять же, порядок добавления байтов зависит от порядка байтов, поэтому вы можете прочитать об этом

Может быть, вы можете конвертировать обратно в C #?

2 голосов
/ 24 июня 2010

Для Луа, посмотрите библиотеку Роберто struct .(Роберто является одним из авторов Lua.) Он является более общим, чем необходимо для конкретного рассматриваемого случая, но не исключено, что вскоре необходимость обмена int сопровождается необходимостью обмена другими простыми типами.или более крупные структуры.

Если исходный порядок байтов приемлем с обеих сторон (что, впрочем, скорее всего, неверно), то вы можете преобразовать число в 4-байтовое целое с помощью:

buffer = struct.pack("l", value)

и обратноснова с:

value = struct.unpack ("l", buffer)

В обоих случаях buffer - это строка Lua, содержащая байты.Если вам нужен доступ к отдельным значениям байтов из Lua, string.byte - ваш друг.

Чтобы указать порядок байтов упакованных данных, измените формат с "l" на "<l" для little-endianили ">l" для big-endian.

Модуль struct реализован на C и должен быть скомпилирован в DLL или эквивалент для вашей платформы, прежде чем он будет использоваться Lua.Тем не менее, он входит в комплект Lua для Windows с батарейками, который является популярным способом установки Lua в системах Windows.

2 голосов
/ 23 июня 2010

Вот некоторые функции в Lua для преобразования 32-разрядного числа дополнения до двух в байты и преобразования четырех байтов в 32-разрядное число дополнения до двух. Можно / нужно сделать гораздо больше проверок, чтобы убедиться, что входящие параметры действительны.

-- convert a 32-bit two's complement integer into a four bytes (network order)
function int_to_bytes(n)
  if n > 2147483647 then error(n.." is too large",2) end
  if n < -2147483648 then error(n.." is too small",2) end
  -- adjust for 2's complement
  n = (n < 0) and (4294967296 + n) or n
  return (math.modf(n/16777216))%256, (math.modf(n/65536))%256, (math.modf(n/256))%256, n%256
end

-- convert bytes (network order) to a 32-bit two's complement integer
function bytes_to_int(b1, b2, b3, b4)
  if not b4 then error("need four bytes to convert to int",2) end
  local n = b1*16777216 + b2*65536 + b3*256 + b4
  n = (n > 2147483647) and (n - 4294967296) or n
  return n
end

print(int_to_bytes(256)) --> 0 0 1 0
print(int_to_bytes(-10)) --> 255 255 255 246
print(bytes_to_int(255,255,255,246)) --> -10
1 голос
/ 23 июня 2010

Для преобразования в байт []:

BitConverter.GetBytes (int)

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

Для преобразования обратнов int:

BitConverter.ToInt32 (byteArray, offset)

http://msdn.microsoft.com/en-us/library/system.bitconverter.toint32.aspx

Хотя я не уверен насчет Lua.

Если вы беспокоитесь о порядке байтов, используйте EndianBitConverter Джона Скита.Я использовал это, и это работает без проблем.

C # поддерживает собственную реализацию htons и ntohs в виде:

Но они работают только на подписанных int16, int32, int64, что означает, что вы, вероятно, в конечном итоге будете выполнять много ненужного приведения, чтобы заставить их работать, и если вы используете бит высшего порядка для чего-либо, кроме подписи целого числа, вы облажались.Был там, сделал это.:: tsk :: :: tsk :: Microsoft не обеспечивает лучшую поддержку преобразования в порядок байтов в .NET.

1 голос
/ 23 июня 2010

Как говорит Нубсис, BitConverter подходит, но не имеет гарантированного порядка байтов.

У меня есть EndianBitConverter класс в MiscUtil , который позволяет вам указывать порядковый номер. Конечно, если вы хотите сделать это только для одного типа данных (int), вы можете просто написать код вручную.

BinaryWriter - это еще один вариант, и этот делает гарантирующим небольшой порядковый номер. (Опять же, MiscUtil имеет EndianBinaryWriter, если вы хотите другие варианты.)

1 голос
/ 23 июня 2010

Преобразование int в байтовый массив и отображение: BitConverter ...

www.java2s.com / Учебник / CSharp / 0280__Development / Convertaninttoabytearrayanddisplay.htm

целое число в байте - ответы Visual Basic .NET

http://bytes.com/topic/visual-basic-net/answers/349731-integer-byte

Как: преобразовать байтовый массив в int (Руководство по программированию в C #)

http://msdn.microsoft.com/en-us/library/bb384066.aspx

1 голос
/ 23 июня 2010

исследование классов BinaryWriter / BinaryReader

...