DPe*_*er1 516
在(不太)早期,所有存在的都是ASCII.这是可以的,因为所需要的只是一些控制字符,标点符号,数字和字母,就像这句话中的那些.不幸的是,今天陌生的全球互通和社交媒体世界没有被预见到,在同一份文件中看到英语,العربية,汉语,ְְִִת,ελληνικά和is并不是太不寻常(我希望我没有打破任何旧的浏览器).
但是出于争论的缘故,让我们说Joe Average是一名软件开发人员.他坚持认为他只需要英语,因此只想使用ASCII.这对于用户 Joe来说可能没问题,但对软件开发人员 Joe来说这不太好.世界上大约一半的人使用非拉丁字符,使用ASCII可以说是对这些人不屑一顾,而且最重要的是,他正在关闭他的软件以适应经济规模庞大且不断发展的经济.
因此,需要包含所有语言的包含字符集.因此来了Unicode.它为每个角色分配一个称为代码点的唯一编号.Unicode优于其他可能集合的一个优点是前256个代码点与ISO-8859-1相同,因此也是ASCII.此外,在称为基本多语言平面(BMP)的区域中,绝大多数常用字符仅可由两个字节表示.现在需要一个字符编码来访问这个字符集,正如问题所示,我将专注于UTF-8和UTF-16.
那么有多少字节可以访问这些编码中的字符?
现在值得一提的是,BMP中没有的字符包括古代文字,数学符号,音乐符号和稀有的中文/日文/韩文(CJK)字符.
如果您将主要使用ASCII字符,那么UTF-8肯定更具内存效率.但是,如果您主要使用非欧洲脚本,那么使用UTF-8的内存效率可能比UTF-16低1.5倍.处理大量文本(如大型网页或冗长的文字文档)时,这可能会影响性能.
注意:如果您知道如何编码UTF-8和UTF-16,请跳到下一节以了解实际应用.
1为了避免与ASCII字符冲突.可以看出,UTF-8和UTF-16无法相互兼容.因此,如果您正在进行I/O,请确保您知道正在使用的编码!有关这些编码的更多详细信息,请参阅UTF常见问题解答.
字符和字符串数据类型:它们如何用编程语言编码?如果它们是原始字节,那么在您尝试输出非ASCII字符的那一刻,您可能会遇到一些问题.此外,即使字符类型基于UTF,也不意味着字符串是正确的UTF.它们可能允许非法的字节序列.通常,您必须使用支持UTF的库,例如ICU for C,C++和Java.在任何情况下,如果要输入/输出默认编码以外的内容,则必须先进行转换.
推荐/默认/主导编码:当选择使用哪种UTF时,通常最好遵循您所使用的环境的推荐标准.例如,UTF-8在网络上占主导地位,而且从HTML5开始,它就是一直是推荐的编码.相反,.NET和Java环境都基于UTF-16字符类型.令人困惑(和错误地),通常对"Unicode编码"进行引用,这通常是指给定环境中的主要UTF编码.
库支持:您使用支持的库有哪些编码?他们是否支持角落案件?由于必要性是发明之母,UTF-8库通常会正确支持4字节字符,因为频繁出现1,2或3字节字符.但是,并非所有声称的UTF-16库都能正确支持代理对,因为它们很少发生.
计数字符: Unicode中存在组合字符.例如,代码点U + 006E(n)和U + 0303(组合波浪号)形成ñ,但代码点U + 00F1形成ñ.它们应该看起来相同,但是一个简单的计数算法将为第一个示例返回2,为后者返回1.这不一定是错的,但也可能不是理想的结果.
比较平等: A,А和Α看起来是一样的,但它们分别是拉丁语,西里尔语和希腊语.你也有C和cases等案例,一个是字母,另一个是罗马数字.另外,我们也要考虑组合字符.有关详细信息,请参阅Unicode中的重复字符.
代理对:这些在SO上经常出现,所以我只提供一些示例链接:
其他?:
wen*_*ang 63
Neu*_*ron 27
Unicode是一个相当复杂的标准.不要太害怕,但要为一些工作做好准备![2]
因为总是需要可靠的资源,但官方报告很大,我建议阅读以下内容:
简要说明:
计算机读取字节,人们读取字符,因此我们使用编码标准将字符映射到字节.ASCII是第一个广泛使用的标准,但仅涵盖拉丁语(7位/字符可代表128个不同的字符).Unicode是一个标准,其目标是覆盖世界上所有可能的字符(最多可容纳1,114,112个字符,意味着最多21位/字符.当前Unicode 8.0总共指定120,737个字符,这就是全部).
主要区别在于ASCII字符可以适合一个字节(8位),但大多数Unicode字符不能.因此使用编码表单/方案(如UTF-8和UTF-16),字符模型如下所示:
每个字符都有一个从0到1,114,111(十六进制:0-10FFFF)的枚举位置,称为代码点.
一个编码形式映射的码点到编码单元序列.一个代码单元是你想在内存中,8位,16位为单位来组织文字等方式.UTF-8使用1到4个8位单元,UTF-16使用1或2个16位单元,以覆盖最大21位的整个Unicode.单位使用前缀,以便可以发现字符边界,更多单位意味着占用比特的前缀更多.因此,尽管UTF-8使用1个字节用于拉丁文脚本,但它需要3个字节用于基本多语言平面内的后续脚本,而UTF-16使用2个字节用于所有这些.这是他们的主要区别.
最后,编码方案(如UTF-16BE或UTF-16LE)将代码单元序列映射(序列化)为字节序列.
字符:π
代码点:U + 03C0
编码格式(代码单位):
UTF-8:CF 80
UTF-16:03C0
编码方案(字节):
UTF-8:CF 80
UTF-16BE:03 C0
UTF-16LE:C0 03
提示:十六进制数字代表4位,因此两位十六进制数字表示一个字节
另外,请查看维基百科中的平面地图,以了解字符集布局
dan*_*n04 18
最初,Unicode旨在具有固定宽度的16位编码(UCS-2).Unicode的早期采用者,如Java和Windows NT,围绕16位字符串构建了它们的库.
后来,Unicode的范围扩展到包括历史字符,这需要16位编码支持的超过65,536个代码点.为了允许在使用UCS-2的平台上表示其他字符,引入了UTF-16编码.它使用"代理对"来表示补充平面中的字符.
同时,许多较旧的软件和网络协议使用8位字符串.制作UTF-8使得这些系统可以支持Unicode而无需使用宽字符.它向后兼容7位ASCII.
InG*_*eek 14
本文解释了所有细节 http://kunststube.net/encoding/
写作缓冲
如果你写一个4字节的缓冲区,?UTF8编码的符号,你的二进制文件将如下所示:
00000000 11100011 10000001 10000010
如果你写一个4字节的缓冲区,?UTF16编码的符号,你的二进制文件将如下所示:
00000000 00000000 00110000 01000010
如您所见,根据您在内容中使用的语言,这将相应地影响您的记忆.
例如,对于此特定符号:?UTF16编码效率更高,因为我们有2个备用字节用于下一个符号.但这并不意味着您必须将UTF16用于日本字母表.
从缓冲区读取
现在,如果您想要读取上面的字节,您必须知道它被写入的编码并正确解码.
例如,如果您将此解码:
00000000 11100011 10000001 10000010
转换为UTF16编码,您将最终?没有?
注意:编码和Unicode是两回事.Unicode是大(表),每个符号映射到唯一的代码点.例如,?符号(字母)有一个(代码点):30 42(十六进制).另一方面,编码是一种在存储到硬件时将符号转换为更合适的方式的算法.
30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.
30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.
Run Code Online (Sandbox Code Playgroud)
为什么unicode?因为ASCII只有127个字符.那些128到255的国家在不同国家有所不同,这就是为什么有代码页.所以他们说让我们有1114111个字符.那么如何存储最高代码点?您需要使用21位存储它,因此您将使用具有32位且浪费了11位的DWORD.因此,如果使用DWORD存储unicode字符,则这是最简单的方法,因为DWORD中的值与代码点完全匹配.但是DWORD数组当然比WORD数组大,当然甚至比BYTE数组更大.这就是为什么不仅有utf-32,还有utf-16.但utf-16表示WORD流,而WORD有16位,那么最高代码点1114111如何适合WORD?这不可以!因此他们将高于65535的东西放入一个他们称为代理对的DWORD中.这样的代理对是两个单词,可以通过查看前6位来检测.那么utf-8怎么样?它是一个字节数组或字节流,但最高代码点1114111如何适合一个字节?这不可以!好吧,所以他们也装了DWORD吧?或者可能是一个词,对吗?几乎是对的!他们发明了utf-8序列,这意味着每个高于127的代码点必须编码为2字节,3字节或4字节序列.哇!但是我们怎样才能发现这样的序列?好吧,高达127的一切都是ASCII,是一个字节.以110开头的是一个双字节序列,以1110开头的是一个三字节序列,以11110开头的是一个四字节序列.这些所谓的"startbytes"的剩余部分属于代码点.现在,根据顺序,必须遵循以下字节.后续字节以10开头,其余位为6位有效负载位并属于代码点.连接startbyte和后续字节的有效负载位,你将获得代码点.这就是utf-8的神奇之处.
Unicode是一种标准,它将所有语言中的字符映射到称为代码点的特定数值.这样做的原因是,它允许使用相同的代码点集进行不同的编码.
UTF-8和UTF-16是两种这样的编码.它们将代码点作为输入,并使用一些明确定义的公式对它们进行编码,以生成编码字符串.
选择特定编码取决于您的要求.不同的编码具有不同的内存要求,并且根据您将要处理的字符,您应该选择使用最少字节序列来编码这些字符的编码.
有关Unicode,UTF-8和UTF-16的更深入的详细信息,您可以查看本文,
小智 5
ASCII - 软件在内存中只为给定字符分配 8 位字节。它适用于英语和采用的(外来词,如 façade)字符,因为它们对应的十进制值在十进制值中低于 128。示例 C 程序。
UTF-8 - 软件为给定的字符分配 1 到 4 个可变的 8 位字节。这里的变量是什么意思?假设您通过浏览器中的 HTML 页面发送字符“A”(HTML 是 UTF-8),A 对应的十进制值为 65,当您将其转换为十进制时,它变为 01000010。这仅需要 1 个字节, 1 字节内存甚至分配给特殊采用的英文字符,如单词 façade 中的 'ç'。但是,当您要存储欧洲字符时,它需要 2 个字节,因此您需要 UTF-8。但是,当您使用亚洲字符时,最少需要 2 个字节,最多需要 4 个字节。同样,表情符号需要 3 到 4 个字节。UTF-8 将解决您的所有需求。
UTF-16 将为每个字符分配最少 2 个字节和最多 4 个字节,它不会分配 1 或 3 个字节。每个字符都以 16 位或 32 位表示。
那为什么会有UTF-16呢?最初,Unicode 是 16 位而不是 8 位。Java 采用了原始版本的 UTF-16。
简而言之,除非您正在使用的语言或平台已经采用了 UTF-16,否则您在任何地方都不需要 UTF-16。
Web 浏览器调用的 Java 程序使用 UTF-16,但 Web 浏览器使用 UTF-8 发送字符。