C# BinaryReader的ReadInt32大小端问题

背景概述

读取网络字节流时候,使用BinaryReader的ReadInt32()方法时候发生了预期外的结果,查阅了微软文档发现是小端( )模式问题,可以通过System.Net.IPAddress.HostToNetworkOrder或BinaryPrimitives.ReadInt32BigEndian 方式来解决

C# BinaryReader的ReadInt32大小端问题_第1张图片

 引申

大端模式(Big-endian)是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
小端模式(Little-endian)是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

优缺点:
大端模式(Big-endian)中地址的变化顺序(低到高)与数据的阅读顺序(高位到低位,如123456我们会从高位开始读,即从左到右)一致。当沿着地址空间找到某个数据内存的时候,我们首先就可以根据他的内容的第一个字节来判断正负。

小端模式(Little-endian)优点:强制类型转化,如int(4字节)转化成short(2字节),直接可以取出前面的低位两字节。另一优点是CPU计算是从数据的低位到高位计算,效率高。当CPU从地址的低位到高位移动的时候,正好数据也是从地位到高位变化,计算高效,但以当今CPU处理速度这点优势已经不值一提了。

Intel的80x86系列芯片是唯一还在坚持使用小端的芯片,ARM芯片默认采用小端,但可以切换为大端;

示例代码

FileStream fileStream = new FileStream(filepath,FileMode.Open);
BinaryReader binaryReader = new BinaryReader(fileStream);
// little-endian模式读取
// int result =binaryReader.ReadInt32(); 

// big-endian模式读取:将由主机字节顺序的整数值转换为网络字节顺序
// int result = System.Net.IPAddress.HostToNetworkOrder(binaryReader.ReadInt32());

// big-endian模式读取
// int result = System.Buffers.Binary.BinaryPrimitives.ReadInt32BigEndian(new ReadOnlySpan(binaryReader.ReadBytes(4)));

或者可以参考java的readInt源码写一个

private int readInt(BinaryReader binaryReader) {
	int ch1 = binaryReader.ReadByte();
	int ch2 = binaryReader.ReadByte();
	int ch3 = binaryReader.ReadByte();
	int ch4 = binaryReader.ReadByte();
	return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

你可能感兴趣的:(.Net系列,c#)