当前位置: 首页 > news >正文

深入理解Emoji(二) —— 字节序和BOM

上篇主要了解了字符集和字符集编码的相关知识,其中有提到字节序的问题,这篇我们便深入探讨下这方面的知识。

字节序

字节顺序,又称端序尾序(英语:Endianness)。在计算机科学领域中,是跨越多字节的程序对象的存储规则。在几乎所有的机器上,多字节对象都被存储为连续的字节序列。例如在Java中,一个int类型的变量a地址为0x100,且x的四个字节将被存储在存储器的0x100, 0x101, 0x102, 0x103位置。而存储地址内的排列则有两个通用规则。一个多位的整数将按照其存储地址的最低或最高字节排列。如果最低有效位在最高有效位的前面,则称小端序;反之则称大端序。在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均按照网络标准转化。

例如假设上述变量x类型为int,位于地址0x100处,它的十六进制为0x01234567,地址范围为0x100~0x103字节,其内部排列顺序依赖于机器的类型。大端法从首位开始将是:0x100: 01, 0x101: 23,..。而小端法将是:0x100: 67, 0x101: 45,..

大端序

高位字节在前,低位字节在后,这是人类习惯的读写数值方法。以一个值为0x0A0B0C0D的int类型变量为例,它的内存为0x100~0x103,则:

内存地址0x1000x1010x1020x103
存储单元0x0A0X0B0X0C0X0D

示例中,最高位字节是0x0A 存储在最低的内存地址处。下一个字节0x0B存在后面的地址处。正类似于十六进制字节从左到右的阅读顺序。

小端序

低位字节在前,高位字节在后,现大部分计算机内部处理都是小端序。同样以上面做例子:

内存地址0x1000x1010x1020x103
存储单元0x0D0X0C0X0B0X0A

最低位字节是0x0D 存储在最低的内存地址处。后面字节依次存在后面的地址处。

实际意义

到这里我们可以发现,在日常开发中,如果不熟悉字节序的情况下,在涉及字节的读取和解析容易出现问题,那么,为什么要区分大端和小端呢,统一不是更方便吗? 其实这里涉及一个效率的问题,计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。如果都是大端序,则计算时需要从高位找到低位,再从低位计算到高位,影响效率。所以,计算机的内部处理都是小端字节序。但是我们人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读取字节,先读第一个字节,再读第二个字节。**如果是大端字节序,先读到的就是高位字节,后读到的就是低位字节。小端字节序正好相反。**只有读取的时候,才必须区分字节序,其他情况都不用考虑。

BOM

我们知道,UTF-16和UTF-32都是多字节的编码规则,那在读取的时候必然也会涉及到字节序的问题,计算机是通过什么判断编码之后的字节序呢,答案就是BOM。

字节顺序标记(byte-order mark,BOM)是位于码点U+FEFF的统一码字符的名称。当以UTF-16或UTF-32来将UCS/统一码字符所组成的字符串编码时,这个字符被用来标示其字节序。它常被用来当做标示文件是以UTF-8、UTF-16或UTF-32编码的标记。而 FFFE 在 UCS 中是不存在的字符,所以不会出现在实际传输中。UCS 规范建议我们在传输字节流前,先传输BOM标记。这样如果接收者收到 FEFF,就表明这个字节流是大端序的;如果收到 FFFE,就表明这个字节流是小端序的。

UTF-8 不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。BOM的 UTF-8 编码是 EF BB BF。所以如果接收者收到以 EF BB BF 开头的字节流,就知道这是 UTF-8 编码了。Windows 就是使用 BOM 来标记文本文件的编码方式的。微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码明确区分开,但这样的文件在 Windows 之外的操作系统里会带来问题。

最后我们再来对比一下携带BOM之后UTF-16编码所得到的结果,其中UTF-16BE代表大端序,UTF-16LE代表小端序:

转载于:https://juejin.im/post/5c00b2cc51882523d316670a

相关文章:

  • 防止系统锁屏-python、C++实现
  • 意见汇总
  • 如何在vue项目中优雅的使用SVG
  • this 指向问题
  • 「BZOJ1385」「Baltic2000」Division expression 解题报告
  • IBM提出8位深度网络训练法,提速4倍同时保持高精度
  • shell脚本中 [-eq] [-ne] [-gt] [-lt] [ge] [le]
  • PEM_密钥对生成与读取方法
  • nginx 根据域名和地址跳转
  • go语言渐入佳境[11]-function2
  • (三)从jvm层面了解线程的启动和停止
  • Apache https
  • 项目实战-Api的解决方案
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • 五个举措:现代化Jenkins 和终结“Jenkinsteins”
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • axios 和 cookie 的那些事
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • java小心机(3)| 浅析finalize()
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • TypeScript迭代器
  • vue-router 实现分析
  • 复杂数据处理
  • 我的zsh配置, 2019最新方案
  • 中文输入法与React文本输入框的问题与解决方案
  • #git 撤消对文件的更改
  • #if和#ifdef区别
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • #控制台大学课堂点名问题_课堂随机点名
  • (03)光刻——半导体电路的绘制
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (二)Linux——Linux常用指令
  • (二十四)Flask之flask-session组件
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (五)Python 垃圾回收机制
  • (一)Dubbo快速入门、介绍、使用
  • (转)jdk与jre的区别
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • @GetMapping和@RequestMapping的区别
  • @ModelAttribute 注解
  • [2017][note]基于空间交叉相位调制的两个连续波在few layer铋Bi中的全光switch——
  • [2023年]-hadoop面试真题(一)
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗
  • [android]-如何在向服务器发送request时附加已保存的cookie数据
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [C# WPF] 如何给控件添加边框(Border)?
  • [C++]二叉搜索树
  • [ComfyUI进阶教程] animatediff视频提示词书写要点
  • [CQOI 2010]扑克牌