浅谈字节序(Byte Order)及其相关操作

02-Cesium-实现天地图标记 首先天地图申请token,然后Cesium-实现天地图标记详细说明 阅读详情

 

最近在为Tokyo Tyrant写一个.NET客户端类库。Tokyo Tyrant公开了一个基于 TCP协议的二进制协议,于是我们的工作其实也只是按照协议发送和读取一些二进 制数据流而已,并不麻烦。不过在其中涉及到了 “字节序”的概念,这本是计算 机体系结构/操作系统等课程的基础,不过我还是打算在这里进行简单说明,并且 对.NET中部分类库在此类数据流处理时的注意事项进行些许记录与总结。

 

字节序(Byte Order)

 

说到程序间的通信,说到底便是发送数据流。我们一般把字节(byte)看作是 数据的最小单位。当然,其实一个字节中还包含8个比特(bit)──有时候我奇 怪为什么很多朋友会不知道bit或是它和byte的关系。当我们拿到一系列byte的时 候,它本身其实是没有意义的,有意义的只是“识别字节的方式”。例如,同样4 个字节的数据,我们可以把它看作是1个 32位整数、2个Unicode、或者字符4个 ASCII字符。

 

同样我们知道,在一个32位的 CPU中“字长”为32个bit,也就是4个byte。在 这样的CPU中,总是以4字节对齐的方式来读取或写入内存,那么同样这4个字节的 数据是以什么顺序保存在内存中的呢?例如,现在我们要向内存地址为a的地方写 入数据0x0A0B0C0D,那么这4个字节分别落在哪个地址的内存上呢?这就涉及到字 节序的问题了。

 

每个数据都有所谓的“有效位(significant byte)”,它的意思是“表示这 个数据所用的字节”。例如一个32位整数,它的有效位就是4个字节。而对于 0x0A0B0C0D来说,它的有效位从高到低便是0A、0B、0C及0D——这里您可以把它 作为一个256进制的数来看(相对于我们平时所用的10进制数)。

 

而所谓大字节序(big endian),便是指其“最高有效位(most significant byte)”落在低地址上的存储方式。例如像地址a写入0x0A0B0C0D之后,在内存中 的数据便是:

 

 

 

而对于小字节序(little endian)来说就正好相反了,它把“最低有效位 (least significant byte)”放在低地址上。例如:

 

 

对于我们常用的CPU架构,如Intel,AMD的CPU使用的都是小字节序,而例如 Mac OS以前所使用的Power PC使用的便是大字节序(不过现在Mac OS也使用Intel 的CPU了)。此外,除了大字节序和小字节序之外,还有一种很少见的中字节序( middle endian),它会以2143的方式来保存数据(相对于大字节序的1234及小字 节序的4321)。

关于字节序的详细说明,您可以参考Wikipedia里的Endianness条目。

相关.NET类库BinaryWriter和BinaryReader

在.NET框架操作数据流的时候,我们往往会使用BinaryWriter和BinaryReader 进行读写。这两个类中都有对应的WriteInt32或是ReadInt32方法,那么它们是如 何处理字节序的呢?从MSDN上我们了解到BinaryReader使用小字节序读取数据。 这意味着:

var stream = new MemoryStream(new byte[] { 4, 1, 0,  0 });
var reader = new BinaryReader(stream);
int i = reader.ReadInt32(); // i == 260

与之类似,自然BinaryWriter也是使用小字节序来写入数据。

 

 

BitConverter

 

有时候我们还会使用BitConverter来转化byte数组及一个32位整数(自然也包 括其他类型),这也是涉及到字节序的操作,那么它们又是如何处理的呢?与 BinaryWriter和BinaryReader的“固定策略”不同,BitConverter的行为是平台 相关的。

 

首先,BitConverter有一个只读静态字段IsLittleEndian,它表示当前平台的 字节序。由于我们为不同的CPU会安装不同的.NET类库,因此您现在如果通过.NET Reflector来查看这个字段会发现它被设置为一个常量true。那么接下来, BitConverter上的各个方便便会根据 IsLittleEndian的值产生不同行为了,例如 它的ToInt32方法:

 

public static unsafe int ToInt32(byte[] value, int  startIndex)

{

   // ...

 

   fixed (byte* numRef = &(value[startIndex]))

   {

     if ((startIndex % 4) == 0)

     {

       return *(((int*)numRef));

     }

     if (IsLittleEndian)

     {

       return numRef[0] | (numRef[1] << 8) |  (numRef[2] << 16) | (numRef[3] << 24);

     }

 

     return (numRef[0] << 24) | (numRef[1] <<  16) | (numRef[2] << 8) | numRef[3];

   }

}

 

显然,这里会根据IsLittleEndian返回不同的值。

 

判断当前平台的字节序

 

在.NET Framework中BitConverter.IsLittleEndian字段是一个常量,也就是 说它在编译期便写入了一个静态的值。那么我们如果想要通过代码来判断当前平 台的字节序,又该怎么做呢?其实这很简单:

 

static unsafe bool IsLittleEndian()

{

   int i = 1;

   byte* b = (byte*)&i;

   return b[0] == 1;

}

 

这里我们通过检查32位整数1的第一个字节来确定当前平台的字节序。当然, 我们也可以使用其他类型,例如:

 

static unsafe bool AmILittleEndian()

{

   // binary representations of 1.0:

   // big endian: 3f f0 00 00 00 00 00 00

   // little endian: 00 00 00 00 00 00 f0 3f

   // arm fpa little endian: 00 00 f0 3f 00 00 00  00

   double d = 1.0;

   byte* b = (byte*)&d;

   return (b[0] == 0);

}

 

这段代码来自mono的BitConverter类库,至于它为什么使用double而不是int ,我也不是很清楚。

 

Buffer.BlockCopy方法

 

.NET类库中自带一个Buffer.BlockCopy方法,它的作用是将一个数组的字节— —不是元素——复制到另一个数组中去。换句话说,一个长度为100的int数组经 过完整的复制后,就变成了长度为50的 long数组,因为一个int为4字节,而long 为8字节。从文档上看,Buffer.BlockCopy是与字节序相关的,也就是说,同样的 .NET 代码在字节序不同的平台上得到的结果可能不同。因此,我建议在使用这个 方法的时候多加小心。

面向特定字节序编程

 

我们知道,BitConverter的工作结果是和当前平台的字节序相关的,但是在很 多时候,尤其是根据某个公开的协议进行通信编程的时候,是需要固定一个字节 序的。例如Tokyo Tyrant便要求每个整数都以大字节序的方式来通信——无论是 发送还是读取。为了保证.NET代码的平台无关性,我们不能直接使用 BitConverter.GetBytes或ToInt32方法进行转化。那么我们该怎么办呢?最直观 的方法自然是手动进行转换:

 

static int ReadInt32(Stream stream)

{

   var buffer = new byte[4];

   stream.Read(buffer, 0, 4);

 

   return buffer[0] | (buffer[1] << 8) | (buffer[2]  << 16) | (buffer[3] << 24);

}

 

由于我们可以通过BitConverter.IsLittleEndian来得到当前平台的字节序, 我们也可以用它进行判断:

 

static int ReadInt32(Stream stream)

{

   var buffer = new byte[4];

   stream.Read(buffer, 0, 4);

 

   if (BitConverter.IsLittleEndian)

   {

     Array.Reverse(buffer);

   }

 

   return BitConverter.ToInt32(buffer, 0);

}

 

static void WriteInt32(Stream stream, int value)

{

   var buffer = BitConverter.GetBytes(value);

 

   if (BitConverter.IsLittleEndian)

   {

     Array.Reverse(buffer);

   }

 

   stream.Write(buffer, 0, buffer.Length);

}

 

此外,我们知道BinaryWriter和BinaryReader都是依据小字节序进行读写的, 因此我们也可以利用这点来读写数据流。要不,接下来就由您试试看如何?

 

 

 

 

 

 

转自:http://www.cnblogs.com/JeffreyZhao/archive/2010/02/10/byte-order-and- related-library.htm

http://www.bianceng.cn/Programming/net/201011/20192_4.htm

大数据领域存算分离:教育行业的数据应用探索 在当今数字化时代,教育行业积累了海量的数据,如学生的学习记录、考试成绩、在线学习行为等。如何高效地存储、管理和分析这些数据,以挖掘其潜在价值,为教育决策、教学改进和学生个性化发展提供支持,成为教育行业面临的重要挑战。大数据领域的存算分离技术为解决这一问题提供了新的思路和方法。本文旨在探索存算分离技术在教育行业的数据应用,分析其原理、优势和实际应用场景,为教育行业的数据管理和分析提供参考。本文共分为十个部分。第一部分介绍背景,包括目的和范围、预期读者、文档结构概述和术语表; 阅读详情

相关推荐

别再让CPU干GPU的活了:CST Studio Suite GPU加速深度调优指南(从驱动版本到任务管理器监控)

本文深入探讨了CST Studio Suite的GPU加速深度调优方法,从NVIDIA驱动版本选择到系统级资源管理,再到实时监控与瓶颈诊断技术。通过科学的驱动优化、GPU资源管理策略和高级调优技巧,显著提升仿真效率,特别适合电磁仿真工程师和硬件加速需求的专业用户。

weixin_28740299的博客 166

java readint 大端格式_fwrite()将在C&的readInt()中的Java字节序中

写入次数27()。int main(){int a = 27;FILE *fp;fp = fopen("/data/tmp.log", "w");if (!fp)return -errno;fwrite(&a, 4, 1, fp);fclose();return 0;}回读使用DataInputStream.readInt的数据(27)():public int readIntDataIn...

weixin_30781567的博客 296

Python实战:5分钟搞定N-CMAPSS航空发动机数据集解析(附完整代码)

本文提供了一份针对N-CMAPSS航空发动机数据集的快速解析实战指南。通过Python的h5py和Pandas库,详细演示了如何高效读取HDF5格式文件、理解数据结构、提取关键特征(如传感器数据与剩余使用寿命RUL),并整合为可用于预测性维护分析的DataFrame,帮助研究者和工程师快速上手这一重要的工业时序数据集。

weixin_29083373的博客 279

一文带你秒懂 字节序(byte order),比特序(bit order),位域(bit field)

本文主要介绍比特序在大小端机器上的排布,以及网卡是如何收发比特的,文末简单介绍了位域的约定

清风 8576

十年芯片资深IC设计工程师面经系列(四)SDC约束

set_driving_cell:当我们的设计是模块级(Block level)的design时,我们的设计前面一般还有其他的设计,那么前面模块的输出便是我们模块的输入,5.1set_false_path:可以单独的时钟或者路径进行约束。set drive :当我们的设计是芯片级(Chip level)的顶层设计时,芯片外围电路要驱动的是负载较大的IO单元,故需要的驱动能力较强,:set_load 是指output端口的负载,设置的值会影响输出到端口的net上的电容,从而影响相应的路径延时。

weixin_47349046的博客 1773

独家开源|RK3588 平台 YOLOv5 Android 源码级解析:NPU 量化、多线程与目标跟踪实战

本文将带你完成一个完整的AI视觉项目:在搭载RK3588芯片的Android开发板上运行实时目标检测与跟踪应用。实战目标:成功运行官方YOLOV5摄像头实时检测案例技术深度:深入理解RKNN开发框架和源码实现核心技能:掌握NPU推理、多线程并发、目标跟踪等关键技术。

m0_71589036的博客 193

字节序(byte order)、比特序(bit order)、MSB/LSB、大端模式/小端模式 概念误混淆

发现之前概念一直混淆,今天就理清楚以作备忘。 前提:内存的读写永远从低地址开始读/写,从低到高!从低到高!从低到高! 内存的读写永远从低地址开始读/写!!! 1、字节序(byte order)、比特序(bit order) 字节序就是串行发送多字节时发送的顺序,比如a=0x12345678,按字节发送是0x12 0x34 0x56 0x78顺序还是0x78...0x12顺序 比特序同理但...

光明磊学习&积累的地方 1万+

C#实现图片裁剪 (附完整源码)

C#实现图片裁剪 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 508

字节序(byte order)和位序(bit order)

**字节序(byte order)和位序(bit order)** lxg@2015/4/27 在网络编程中经常会提到网络字节序和主机序,也就是说当一个对象由多个字节组成的时候需要注意对象的多个字节在内存中的顺序。 以前我也基本只了解过字节序,但是有一

liuxingen的专栏 3万+

ShaderJoy —— 简单又神奇的 “合体” 函数【GLSL】

smin 函数 它实际上有两种常见的实现方式 多项式 指数 多项式 smin 函数图 其对应的代码为 float smin( float a, float b ) { // 多项式 const float k = 0.5; float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0); return mix(b, a, h) - k * h * (1.0 - h); } 从上图中我们可以很明显的看出有两处不连...

ShaderJoy 的兴趣技术杂货铺 1857

喷涂机器人系列编程:ABB IRB 5500_(2).ABB IRB 5500喷涂机器人系统架构与组件

ABB IRB 5500喷涂机器人系统不仅在性能上表现出色,而且在安全和维护方面也提供了全面的解决方案。通过本文的详细介绍,希望读者能够更好地理解和掌握这一系统的架构和功能,为实际应用提供有力支持。

zhubeibei168的博客 778

字节序详细解读

概念来了!!!看概念肯定完犊子,接下来我们明确几个概念。。。什么是高字节?什么是低字节?在一个n进制的位中,最左边的位叫最高有效位,最右边的叫最低有效位。举个例子,1个int的整数123456789按照从右向左的方向,二进制中,0101是低字节,最左边的0000是高字节;十六进制中,15是低字节,07是高字节。再通俗一点解释就是:8421码的,8这端为高位,1这端为低位,相应的字节则分别称为高位字节和低位字节。补充:进制转换在内存中,多字节对象都是被存储为连续的字节序列。假设将int整型在内存中的起始地址(

打不倒的程序猿 9656

SystemVerilog从入门到实战

SystemVerilog复合数据类型概述 SystemVerilog增强了Verilog的数据建模能力,提供多种复合数据类型: 数组类型:包括定宽数组(固定大小)、动态数组(运行时分配)和多维数组,支持高效索引访问。 队列:结合数组和链表特性,支持两端快速插入/删除操作,提供push/pop等方法。 关联数组:键值对存储结构,支持稀疏数据存储和快速查找,提供exists/delete等方法。 结构体:组合不同类型数据成员,支持打包(packed)形式以优化存储空间。 枚举类型:为数值赋予语义名称,支持状态

2301_79143213的博客 1227

[转]浅谈字节序(Byte Order)及其相关操作

<br />摘自http://www.cnblogs.com/JeffreyZhao/archive/2010/02/10/byte-order-and-related-library.html<br />2010-02-10 23:05 by Jeffrey Zhao, 7642 visits, 网摘, 收藏, 编辑<br />最近在为Tokyo Tyrant写一个.NET客户端类库。Tokyo Tyrant公开了一个基于TCP协议的二进制协议,于是我们的工作其实也只是按照协议发送和读取一些二进制数据流而

wang37921的专栏 844

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

浅谈字节序(Byte Order)及其相关操作(转自老赵)

最近在为Tokyo Tyrant写一个.NET客户端类库。Tokyo Tyrant公开了一个基于TCP协议的二进制协议,于是我们的工作其实也只是按照协议发送和读取一些二进制数据流而已,并不麻烦。不过在其中涉及到了“字节序”的概念,这本是计算机体系结构/操作系统等课程的基础,不过我

tianwailaibin的专栏 1283

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【编程技术】字节序(Byte Order)

字节序(Byte Order),又称端序或字节顺序,指多字节数据在内存中的存储顺序。它是计算机体系结构中的一个重要概念,直接影响数据在不同系统间的传输和解析。

weixin_43510208的博客 1281

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

字节序 byte order

我们在做网络相关的编程时,经常会遇到网络字节序和主机字节序的问题:当我们要把数据发送到网络中进行传输时,需要把数据先转换为网络字节序再发送;当我们从网络中接收到数据后,需要先转换为主机字节序才能使用。 Big Endian和Little Endian字节序是计算机体系结构的一个基本属性,每台计算机都是按照自己的字节序方式处理数据的。那到底什么是字节序呢?简单的说,字节序是计算机处理数据

sinkingship的专栏 1070

字节序(Byte Order)

字节序与平台字节序转换字节序(Byte Order)是指数据在内存中存储时字节的排列顺序。由于不同的计算机体系结构可能采用不同的字节序,因此理解字节序非常重要,特别是在处理多平台数据传输或存储时。

weixin_50993868的博客 538
上一篇: 改善C#程序的建议9:使用Task代替ThreadPool和Thread (转)
下一篇: sql2005 的树形递归查找
learningaginlearnin
博客等级 码龄23年 9粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值