为了要编码Unicode大于0xFFFF的字符,人们对UCS-2编码进行了拓展,创造了UTF-16编码,它是变长的,在BMP范围内,UTF-16与UCS-2完全一致,而BMP之外UTF-16则使用4个字节来存储...UTF-16编码(四字节),把前两个字节和后两个字节各作为一个Unicode数,然后赋值给String,示例代码如下所示。...然后它就选择了一种绝对不会产生丢失的方案,它假设这是ISO-8859-1编码的数据,然后查ISO-8859-1的代码页,得到Unicode序列,因为ISO-8859-1是按字节编码的,而且不同于ASCII...编译的时候我们没有指定encoding参数,所以编译器会默认以GBK方式去解码,对UTF-8和GBK有点了解的应该会知道,一般一个中文字符使用UTF-8编码需要3个字节,而GBK只需要2个字节,这就能解释为什么字符数的奇偶性会影响结果...,对应结果图中的三个奇怪字符。
但是笔者在开发一个 Go 的 JSON 编解码库的过程中,除了自己趟过各种奇奇怪怪的问题之外,也认识到广大程序员们对 JSON 各种奇奇怪怪的用法和使用姿势。...但是在实际操作中,这种转义太浪费字节序列了,各种语言对 string 类型进行操作时,习惯性地按照本身的字符串在内存中的默认编码格式照搬到 JSON 序列化上了。...如果你这么做,那么作为一个通用库来说……图片严格来说,\uXXXX 其实是对 UTF-16 编码的转写。这是一个比较少用的编码格式。...我们都知道,UTF-8 是一个变长的编码格式,它编码的基本单位是 1 个字节。受早期 Windows 16位 wchar 的影响,有些人可能会误以为UTF-16 是定长的 2 个字节。...其实并不然,对于大于 65535 的 unicode 码点,UTF-16 使用 4 个字节编码,而 JSON 只需要将编码后的两个半字(half world)按顺序使用 \uXXXX 转写出来就可以了。
大家好,又见面了,我是你们的朋友全栈君。 Java中理论说是一个字符(汉字 字母)占用两个字节。...无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码;将String的内容用外码编码好,结果放在一个新byte[]返回。...题外话2:前面我说Java的内码时说得比较松,留下了“不总是使用UTF-16作为内码,但是用户无法感知区别”的余地。...反之,只要有任何一个字符超出了ASCII的编码范围,就退回到用char[](UTF-16序列)来存储。...ASCII编码也是一种定长编码,而且其涵盖的字符是UTF-16的真子集;用户在对一个“压缩”的字符串访问其内容时(例如String.charAt()),只需对ASCII字符做无符号扩展就可以得到对应的UTF
Unicode的目标就如同其名称的含义一样:“实现字符编码统一” Unicode标准的实现方案有如下三种:UTF-8、UTF-16和UTF-32**. UTF-8是变长编码,使用1到4个字节。...此外,字节首部连续1的个数就代表了该字符编码后所占的字节数。目前全世界的网页编码绝大多数使用的就是UTF-8,占比接近90%。...输出编码后的字节序列可以发现,起始的两个字节都是:"fe ff"。 Java的char类型用什么编码格式?Java语言规范规定了Java的char类型使用的是UTF-16。...这就是为什么Java的char占用两个字节的原因。此外,Java标准库实现的对char与String的序列化规定使用UTF-8。...fe ff"在Unicode标准中属于"noncharacters",只用于内部使用。所以, 在输出该字节序列的时候,没有该码元对应的字符,对于不识别字符,就会用��替代。 3.
记得在前几年,Emoji的问题还蛮火的,大家都挺奇怪,为什么有的Emoji在JavaScript里的长度是2,还有一个''的问题好像更火一些: 二、字符编码的早期历史 (一)从电报说起 在电报还没发明以前...ISO 8859没有使用ISO 2022中的G2、G3区域,也不再使用ISO 2022定义的用来在不同的字符编码集或在同一个编码集的G0、G1、G2、G3区域间转换的“控制字符转义序列”。...在编码序列中查找第N个编码是一个常数时间操作。相比之下,其他可变长度编码需要进行循序访问操作才能在编码序列中找到第N个编码。...这使得在计算机程序设计中,编码序列中的字符位置可以用一个整数来表示,整数加一即可得到下一个字符的位置,就和ASCII字符串一样简单。 UTF-32的主要缺点是每个码位使用四个字节,空间浪费较多。...JavaScript为什么会有这样的表现了,实际上TC39就针对这个问题探讨过: 所以ES6提供了访问Unicode码点的方法: 顺便提一下,新一代的编程语言,已经采用utf-8来实现字符串了(我始终觉得代理对就是一个蹩脚的方式去兼容当时
但是在底层它还是一个个的二进制数,是由一个个的字节组成的(也就是byte),只不过python根据指定的字符集编码"强行"将字节序列显示为字符。...>>> a = "我">>> a'我'>>> ord(a)25105>>> a.encode()b'\xe6\x88\x91'根据指定字符集,底层的字节序列和字符序列间的转换过程完全无需人为的参与,python...比如中国有GBK的各种编码,还有全球通用的编码类型unicode、utf-8、utf-16等。无论什么编码,内部都包含ascii编码(也有例外,比如utf-16),它只需单个字节。...例如,使用utf-8编码"我"字,得到一个bytes序列,然后使用gbk解码这个bytes序列。...如果使用文本编辑器一样的工具去显化这个过程,得到的将是乱码字符。
Character Encoding Form(CEF):将由一个或多个 Code Unit(定长的 Bit 序列)组成的序列与 Code Point 关联起来的映射。...UTF-16 UTF-16 中,每个 Code Point 使用 2 个字节或 4 个字节表示。...在解析使用 UTF-16 大端编码的字节流时,首先判断 Code Unit 是否在 U+D800~U+DBFF 范围内: 如果是,则与其后相邻的 Code Unit 放在一起解码。...在解析使用 UTF-16 小端编码的字节流时,首先判断 Code Unit 是否在 U+DC00~U+DFFF 范围内: 如果是,则与其后相邻的 Code Unit 放在一起解码。...设当前所使用的字节数为 n,第一个字节的前高 n 位设为 1,第高 n + 1 位设为 0,后续字节的高 2 位均设为 10。
JavaScript 因历史原因,使用的是近似于 UTF-16 的 UCS-2 方案(编码中操作处理时表现为 UCS-2,浏览渲染显示时基于 UTF-16 重新显示为 Unicode 字符)。...汉字:“我” 作为常用汉字的“我”字,码点 25105(0x6211): 由于 0x6211 没有超过两个字节,所以使用 UTF-16 相当于直接对 Unicode 码点做16进制编码转换,仍只占用2字节...使用 UTF-16 编码时,超过 0xffff 的它需要借助 低位代理&高位代理 进行辅助表示,也使用了4个字节。...通过输出结果我们可以看出,其中 \x8C 和 \x22 都被当成单个的字符进行处理了,而 JavaScript 中 UCS-2/UTF-16 的实现下,一个字符是以2或4个字节进行存储的。...而服务端实现 JSON 序列化时可能考虑到了这点,提前将其变为基于 UTF-16 的转义书写字符串字面量,这样浏览器内的 JavaScript 反序列化后就可以正常得到预期的 谢谢 了。
UTF-8应该是目前应用最广泛的一种Unicode编码方式(但不是最早面世的,UTF-16要早于UTF-8面世)。它是一种使用8位码元(即单字节码元)的变宽(即变长或不定长)码元序列的编码方式。...由于UTF-16对于ASCII字符也必须使用两个字节(因为是16位码元)进行编码,存储和处理效率相对低下,并且由于ASCII字符经过UTF-16编码后得到的两个字节,高字节始终是0x00,很多C语言的函数都将此字节视为字符串末尾从而导致无法正确解析文本...UTF-8的码元由8位单字节组成;在UTF-8中,因为码元较小的缘故,Unicode码点值被映射到一个、两个、三个或四个码元;换言之,UTF-8使用一个至四个8位单字节码元的序列来表示Unicode字符...在将逻辑形式的码元序列(或可称之为逻辑编码)映射为物理形式的字节序列(或可称之为物理编码)时,因系统平台的差异,存在一个字节序(Byte-Order字节顺序)的问题。...对于已注册的字符编码(这里的字符编码实际为字符编码方式CEF)UTF-16和UTF-32来说,则必须在文本开头使用BOM。 4. 不同编码的字节序列中所使用的字节序标记BOM本身的字节序列呈现: ?
这之后,Unicode逐渐占据了主导地位,并引入了UTF-16编码方式。为什么要引入UTF-16编码方式呢?...作为逻辑意义上的UTF-16编码(码元序列),由于历史的原因,在映射为物理意义上的字节序列时,分为UTF-16BE(Big Endian)、UTF-16LE(Little Endian)两种情况。...比如,“ABC”这三个字符的UTF-16编码(码元序列)为:00 41 00 42 00 43;其对应的各种字节序列如下: ?...例如代码中的字符串,在内存中相应的字节流就是UTF-16字节序列的。(注意,UTF-16编码在Windows环境中被误用为“widechar”和“Unicode”的同义词) 8....UTF-16一方面使用变长码元序列的编码方式,相较于定长码元序列的UTF-32算法更复杂(甚至比同样是变长码元序列的UTF-8也更为复杂,因为引入了独特的代理对这样的代理机制);另一方面仍然占用过多字节
字节顺序标记 BOM在使用 ASCII 编码的时候,因为每个字符都可以用一个字节表示,所以不存在先传高位或先传低位的问题。...但对于 UTF-8、UTF-16 等多字节编码来说,有时需要一种机制来标识出一段数据采用的是哪种字节序列,以便不同程序之间能够正确的传输、解码信息。...但 BOM 的使用是可选的,因为它是一个 Unicode 字符,可能会影响一些使用 ASCII 编码读取第一个字符的程序。...=utf-16le以上输出表示 foo.txt 是一个采用 UTF-16 小端序列编码的文件。...= nil { log.Fatal(err)}defer file.Close()// 手动生成一个解码器,指定编码为 UTF-16,字节序列为小端序列utf16le := unicode.UTF16
原有的ASCII字符对应的码位不变,也是使用一个字节来存储。 (2)除拓展的生僻字外,大部分汉字采用双字节编码。也就是说GB系列编码存储也采用的是变长存储方案。...使用UTF-8编码时,大部分汉字转换后需要用三字节存储。 UTF-16 UTF-16实现方案则介于UTF-8和UTF-32之间。...字符会构成一个emoji表示序列。...base的表情加上一个modifier修饰符后会构成一个emoji修饰符序列。...有了这些组合方式的基础,再回头看前面的金发黑人男子就不难理解为什么它由那么多Unicode字符组成了。本质也是通过前面所述的三种表示规则组成得到的。
当我们把字符映射为数字之后,我们就得到了一个 字符集(Character Set) 。...而UTF-16是用2个字节或4个字节来表示码点的,这将取决于码点在Unicode中哪个Plane中,如果码点在最基本的BMP平面中,那么UTF-16将使用2个字节来编码,否则将使用4个字节来编码。...最复杂,最灵活,用的最多的就是UTF-8编码方式了。他可以根据码点的范围使用1到4个字节来编码。 码元和码点 前面我们已经知道了,码点是由一个或多个码元组成的,我们用一个简单的例子来了解下。 ?...大端序:高位字节在前,低位字节在后 小端序:低位字节在前,高位字节在后 举个例子,汉字“语”用UTF-16编码,大端序的结果是: 8A9E ,小端序的结果是: 9E8A 为什么会有字节序这种奇怪的问题存在呢...第四行就比较奇怪了,按照UTF-16编码方式,”语“ 的编码结果应该是 8b4d ,开头多出来的两个字节是什么情况呢?
哈哈,因为还剩下最后一个char型了,因为char型会牵涉到Unicode编码相关,因此我决定先科普一下字符集编码。 我儿子现在上小学,他们从1年级就开始学英语,为啥啊?...至于为什么不直接发布区位码,我也没查到相关资料,个人猜测是为了避开ASCII码的控制字符。...为什么电子邮件和网页都经常会出现乱码,就是因为信息的提供者可能是日文的ANSI编码体系,信息的读取者可能是中文的编码体系,他们对同一个二进制编码值进行显示,采用了不同的编码,导致乱码。...二是给定一个UTF-16字节流,如何确定Unicode编码: 对于一个给定的Unicode编码U,如果是属于平面0,即U+0000到U+FFFF,把对应的Unicode编码补足为16位,就是UTF-16...考虑到兼容性的问题,Java换成了UTF-16编码,char用来表示一个代码单元。 因此,在实际工作和实践中,尽量避免使用char类型,除非你对所要操作的内容非常熟悉。
考虑到这一点造成的混乱,我认为最好在调试时以不同的方式检查字符串,至少在你觉得奇怪的事情正在发生的情况下应该这样做。...或者,作为检查文本的一种交互方式,你可以使用我的 Unicode Explorer 小应用——只需要输入文本,就可以查看对应的字符,UTF-16代码单元和UTF-8字节。...这导致在使用代码时,在U+FFFF以上的字符在字符串中表示为两个字符。本质上,string使用UTF-16字符编码形式。大多数开发人员可能不需要了解关于这一点的更多信息,但至少要注意这一点。...至于为什么string使用UTF-16字符编码形式,请参阅Why does .net uses the UTF16 encoding for string , but uses utf8 as default...它被重复使用Replace方法,用一个空格替换所有的双重空格,并检查是否已经完成使用IndexOf,以便多个空格折叠到一个空格。不幸的是,由于两个空格间的原始字符串中的“奇怪”字符,转换将失败。
为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言。...如果一个字节,以 10 开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节 Java 中需要编码的场景 前面描述了常见的几种编码格式,下面将介绍 Java 中如何处理对编码的支持,什么场合中需要编码...它适合在本地磁盘和内存之间使用,可以进行字符和字节之间快速切换,如 Java 的内存编码就是采用 UTF-16 编码。...,而数据经过网络传输都是以字节为单位的,所以所有的数据都必须能够被序列化为字节。...例如将“ab”两个字符通过某种编码转变成一个奇怪的字符,虽然字符数从两个变成一个,但是如果采用 UTF-8 编码这个奇怪的字符最后经过编码可能又会变成三个或更多的字节。
,规定了符号对应的二进制代码 至于这个二进制代码如何存储则没有任何规定,也就是说它是一种编码规定 是编码字符集,而不是实际的编码方案 最初Unicode使用一个16位长度的二进制序列,也就是最多支持...一个字符对应一个二进制序列 基本平面中使用四位十六进制数 在零号平面以外的字符则需要使用五位或六位十六进制数了 编码方式 Unicode 没有规定字符对应的二进制码在计算机中如何存储,只是规定了他的值是多少而已...比如数字1 他的码点是1 假如我用两个字节来存储,每个字节的前两位我当做其他的标志位, 设置为11 那么可能结果是这样子的11000000 11000001显然,他的值并不是1 编码方式只是可以保证,你的字符是按照指定的字符集进行编码的也就是说如果你告诉我拿出来码点为...,可变长 使用 1 - 4 个字节表示一个字符,根据字符的不同变换长度 规则可以把编码分解成两部分,head和bodyhead中记录需要字节的个数,使用第一个字节中1 的个数来表示body记录真实的数据...替换掉x即可 字节序 根据我们上面描述的utf8 以及utf16都有可能使用不止一个字节进行编码 其实还有很多其他数据也不仅仅是一个字节进行表达 在计算机中最终都是二进制序列的形式 比如utf
比如,下面我所列的几条: 1、由于使用单引号,以“ ”为分割符,使用PHP函数explode分割字符串,不能正常分割。 原因:这个涉及到单引号与双引号的区别,在单引号中反斜杠不能被解析。...在utf-8文件中常用BOM来表明这个文件是UTF-8文件,而BOM的本意实在utf16中用来表示高低字节序列的。...在字节流之前有 BOM表示采用低字节序列(低字节在前面),而utf8不用考虑字节序列,所以其实有无BOM都可以。UTF-8以字节为编码单元,没有字节序的问题。...UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是 594E,“乙”的Unicode编码是4E59。...如果我们收到UTF-16字节流“594E”,那么这是 “奎”还是“乙”? 如果文件保 存时,选择了使用 BOM,会使页面显示不正常。
另举一例: Java标准库实现的对char与String的序列化规定使用UTF-8作为外码。Java的Class文件中的字符串常量与符号名字也都规定用UTF-8编码。...同一个字符在不同的编码下可能占不同的字节。...(因为 UTF-8 是 变长编码) 而 Java 中的 char 本质上是 UTF-16 编码。而 UTF-16 实际上也是一个变长编码(2 字节或 4字节)。...如果一个抽象的字符在 UTF-16 编码下占 4 字节,显然它是不能放到 char 中的。换言之, char 中只能放 UTF-16 编码下只占 2 字节的那些字符。...而 getBytes 实际是做编码转换,你应该显式传入一个参数来指定编码,否则它会使用缺省编码来转换。
# Unicode的实现方式 UTF-8 使用一至四个字节为每个字符编码 UTF-16 使用二或四个字节为每个字符编码 UTF-32 使用四个字节为每个字符编码 举个例子:Unicode规定了一个中文字符...多字节序列的开始,或中间字节;剩余的比特连接起来表示编码点的下标。...UTF-16 你可能遇到的另一个编码是 UTF-16,它使用 16-bit 字,每个字符被存储为 1 个或 2 个字节=16bit.和 UTF-8 一样,我们可以用二进制前缀的形式表示 UTF-16 的编码规则...至少,你得 “舍去” 最近的编码点;但更好的是,舍去最近的字位簇 除此以外,你可以通过舍弃它的一个注音符号破坏一个字符,中断一个 jamo 序列或 ZWJ 序列 字符乱码 描述: 为什么会出现字符乱码的情况...编码,再使用UTF-8解码,得到的字符就是一串问号这就是乱码了。
领取专属 10元无门槛券
手把手带您无忧上云