转换为或来自十六进制字符串时如何设置字节顺序

时间:2011-01-31 15:48:45

标签: c# .net endianness

要将整数转换为十六进制格式的字符串,我使用ToString(“X4”),如下所示:

int target = 250;    
string hexString = target.ToString("X4");

要从十六进制格式的字符串中获取整数值,我使用Parse方法:

int answer = int.Parse(data, System.Globalization.NumberStyles.HexNumber);

然而,我正在交换数据的机器以相反的顺序放置字节。

为了保持样本数据,如果我想发送值250,我需要一个字符串“FA00”(不是00FA,这是hexString是什么)同样如果我得到“FA00”我需要将其转换为250而不是64000

如何设置这两种转换方法的字节顺序?

2 个答案:

答案 0 :(得分:4)

这不是一个内置选项。所以要么字符串工作来交换周围的字符,要么有点位移,即。

int otherEndian = (value << 16) | (((uint)value) >> 16);

答案 1 :(得分:4)

马克的答案似乎已经被接受,已经解决了OP的原始问题。但是,从问题文本中我不清楚为什么。这似乎仍然需要交换字节,而不是Marc的答案所做的字节对。我不知道任何合理的常见情况,一次交换16位是有意义的或有用。

对于规定的要求,恕我直言,写这个更有意义:

int target = 250; // 0x00FA

// swap the bytes of target
target = ((target << 8) | (target >> 8)) & 0xFFFF;

// target now is 0xFA00
string hexString = target.ToString("X4");

注意,上面假设我们实际上处理的是16位值,存储在32位int变量中。它将处理16位范围内的任何输入(注意需要屏蔽高16位,因为它们被<<运算符设置为非零值。)

如果交换32位值,则需要这样的内容:

int target = 250; // 0x00FA

// swap the bytes of target
target = (int)((int)((target << 24) & 0xff000000) |
    ((target << 8) & 0xff0000) |
    ((target >> 8) & 0xff00) |
    ((target >> 24) & 0xff));

// target now is 0xFA000000
string hexString = target.ToString("X8");

同样,需要屏蔽以隔离我们移动到特定位置的位。需要先将<< 24结果转换回int或其他三个字节,因为0xff000000uintUInt32)字面值并导致&表达式要扩展为longInt64)。否则,您将收到每个|运算符的编译器警告。


在任何情况下,由于这在网络方案中最常见,因此值得注意的是.NET提供了可以帮助执行此操作的辅助方法:HostToNetworkOrder()NetworkToHostOrder()。在这种情况下,“网络顺序”始终是大端,“主机顺序”是托管当前进程的计算机上使用的任何字节顺序。

如果您知道自己收到的是big-endian数据,并且希望能够在流程中将其解释为正确的值,则可以调用NetworkToHostOrder()。同样,如果您需要在需要big-endian的上下文中发送数据,则可以调用HostToNetworkOrder()

这些方法仅适用于三种基本整数类型:Int16Int32Int64(在C#中,shortint和{ {1}},分别)。它们也返回传递给它们的相同类型,因此您必须注意符号扩展。问题中的原始示例可以像这样解决:

long

再次需要屏蔽,否则方法返回的int target = 250; // 0x00FA // swap the bytes of target target = IPAddress.HostToNetworkOrder((short)target) & 0xFFFF; // target now is 0xFA00 string hexString = target.ToString("X4"); 值将被符号扩展为32位。如果在结果中设置了比特15(即short),则最终0x8000值也将设置其最高16比特。只需对变量使用更合适的数据类型(例如,int,当数据需要对16位值进行签名时),可以在不屏蔽的情况下解决这个问题。

最后,我将注意到shortHostToNetworkOrder()方法,因为它们只是交换字节,彼此相同。当机器架构是little-endian 时,它们都交换字节。实际上,.NET实现只是为NetworkToHostOrder()调用NetworkToHostOrder()。主要有两种方法,以便.NET API与原始BSD套接字API匹配,其中包括HostToNetworkOrder()htons()等函数,而API又包含两个转换方向的函数,主要是为了它在代码中清楚地知道是从网络接收数据还是向网络发送数据。


†当机器架构是big-endian时什么都不做......它们作为通用的字节交换功能并不实用。相反,期望网络协议始终是大端的,并且这些函数用于确保交换数据字节以匹配机器架构。