我需要将一个int转换为字节[],其中一种方法是使用BitConverter.GetBytes()。但我不确定这是否符合以下规格:
XDR有符号整数是一个32位的数据,它将整数编码为 范围[-2147483648,2147483647]。整数表示为 二的补符号。最高和最低有效字节为 分别是0和3。整数的声明如下:
来源:RFC1014 3.2
我怎么能做一个int到字节的转换,将满足上述规范?
我需要将一个int转换为字节[],其中一种方法是使用BitConverter.GetBytes()。但我不确定这是否符合以下规格:
XDR有符号整数是一个32位的数据,它将整数编码为 范围[-2147483648,2147483647]。整数表示为 二的补符号。最高和最低有效字节为 分别是0和3。整数的声明如下:
来源:RFC1014 3.2
我怎么能做一个int到字节的转换,将满足上述规范?
当前回答
RFC只是试图说明一个有符号整数是一个正常的4字节整数,字节以大端序排列。
现在,您很可能正在一台小端序机器上工作,而BitConverter.GetBytes()将为您提供反向的字节[]。所以你可以试试:
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;
其他回答
getbytes (int)几乎做了你想要的,除了字节顺序是错误的。
可以使用IPAddress。在使用BitConverter之前交换整数值内的字节的hosttonnetwork方法。GetBytes或使用Jon Skeet的EndianBitConverter类。两种方法在可移植性方面都做了正确的事情(tm)。
int value;
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value));
为什么上面示例中的所有这些代码…
具有显式布局的结构以两种方式工作,并且没有性能影响。
更新:因为有一个关于如何处理字节序的问题,我添加了一个接口,说明如何抽象它。另一个实现结构可以处理相反的情况
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 => b1;
public byte B2 => b2;
public byte B3 => b3;
}
RFC只是试图说明一个有符号整数是一个正常的4字节整数,字节以大端序排列。
现在,您很可能正在一台小端序机器上工作,而BitConverter.GetBytes()将为您提供反向的字节[]。所以你可以试试:
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;
using static System.Console;
namespace IntToBits
{
class Program
{
static void Main()
{
while (true)
{
string s = Console.ReadLine();
Clear();
uint i;
bool b = UInt32.TryParse(s, out i);
if (b) IntPrinter(i);
}
}
static void IntPrinter(uint i)
{
int[] iarr = new int [32];
Write("[");
for (int j = 0; j < 32; j++)
{
uint tmp = i & (uint)Math.Pow(2, j);
iarr[j] = (int)(tmp >> j);
}
for (int j = 32; j > 0; j--)
{
if(j%8==0 && j != 32)Write("|");
if(j%4==0 && j%8 !=0) Write("'");
Write(iarr[j-1]);
}
WriteLine("]");
}
}
}```
When I look at this description, I have a feeling, that this xdr integer is just a big-endian "standard" integer, but it's expressed in the most obfuscated way. Two's complement notation is better know as U2, and it's what we are using on today's processors. The byte order indicates that it's a big-endian notation. So, answering your question, you should inverse elements in your array (0 <--> 3, 1 <-->2), as they are encoded in little-endian. Just to make sure, you should first check BitConverter.IsLittleEndian to see on what machine you are running.