2010-06-23 125 views
3

我需要通过NetworkStream发送一个整数。问题是我只能发送字节。 这就是为什么我需要分割四个字节的整数并发送这些,并在另一端转换回int。如何将int转换为字节数组然后返回?

现在我只需要在C#中使用它。但是对于最后的项目,我需要将这四个字节转换为Lua中的int。

[编辑] 在Lua怎么样?

+0

如何为Lua端请求一个单独的(但相关的)问题,以便那些答案明显独立于C#答案... – RBerteig 2010-06-24 00:23:11

回答

6

尝试

BitConverter.GetBytes()

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

只需记住的是,在返回数组中的字节的顺序取决于系统的字节序。

编辑: 至于Lua部分,我不知道如何转换回来。你总是可以乘以16来获得按位移4的相同功能。它不是很漂亮,我会想象有一些库或实现它的东西。同样,添加字节的顺序取决于字节顺序,因此您可能需要阅读该字节

也许您可以转换回C#?

1

调查的BinaryWriter/BinaryReader在类

1

由于Nubsis说,BitConverter是适当的,但没有保证字节顺序。

我有一个EndianBitConverterMiscUtil它允许您指定字节顺序。当然,如果您只想为单个数据类型(int)执行此操作,则只需手动编写代码即可。

BinaryWriter是另一种选择,并且这个确实保证小的字节顺序。 (同样,如果你想要其他选项,MiscUtil有EndianBinaryWriter)。

8

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; 
} 
+0

我更喜欢这种方法,因为BitConverter不会重用现有数组(例如ref byte []) ),并总是创建一个新的数组 - 我想这会在需要完成许多转换时损害性能。 – Libor 2016-06-28 13:42:47

1

要转换为字节[]:

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。

如果您担心使用John Skeet的EndianBitConverter。我已经使用它,它可以无缝工作。

C#支持自己的实现htons和ntohs和为:

但他们只对签署INT16,INT32工作,Int64的,这意味着你可能会结束做了很多不必要的工作来使它们工作,如果你使用最高位来除了签名整数之外的任何东西,那么你就搞砸了。去过也做过。 :: tsk :: :: tsk :: Microsoft未在.NET中提供更好的字节顺序转换支持。

2

以下是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 
+0

这个人很好,虽然我个人从未跟随过卢阿式(......和......)或任务。如果在这种情况下使用,对我来说很好。 – shabunc 2012-01-07 16:20:55

2

对于Lua,请查看Roberto的struct库。 (罗伯托是Lua的作者之一)。对于特定的案例来说,它比所需要的更普遍,但是交换一个int的需求不是不太可能需要互换其他简单类型或更大结构。

假设本地字节顺序是在两端上可接受的(这可能是一个坏的假设,顺便),则可以将数字转换为一个4字节整数用:

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

并再次返回:

值= struct.unpack( “L”,缓冲液)

在两种情况下,buffer是包含字节一个Lua字符串。如果您需要从Lua访问单个字节值,则string.byte是您的朋友。

要指定打包数据的字节顺序,改变从"l"格式,以"<l"为小端或">l"为大端。

struct模块在C语言中实现,必须在Lua可以使用它之前将其编译为一个DLL或同等的平台。也就是说,它被包含在Lua for Windows包含电池的安装包中,这是在Windows系统上安装Lua的常用方式。

相关问题