关于编码:什么是unicode、utf-8、utf-16?

What is Unicode, UTF-8, UTF-16?

Unicode的基础是什么?为什么需要UTF-8或UTF-16?我在谷歌上研究过这个,也在这里搜索过,但我不清楚。

在VSS中,进行文件比较时,有时会出现一条消息,说明两个文件的UTF不同。为什么会出现这种情况?

请用简单的术语解释。


为什么我们需要Unicode?

在(不是太)早期,所有存在的都是ASCII码。这没关系,因为只需要一些控制字符、标点、数字和字母,就像这句话中的那些。不幸的是,今天这个陌生的全球交流和社交媒体世界并没有被预见到,而且看到英语也不算太不寻常,??????????,是吗???????????,ελληκ??????????????在同一个文档中(我希望我没有破坏任何旧的浏览器)。好的。

但是为了争论,让我们假设JoeAverage是一个软件开发人员。他坚持说他只需要英语,因此只想使用ASCII。对于用户Joe来说,这可能很好,但是对于软件开发人员Joe来说,这并不好。世界上大约有一半的人使用非拉丁语字符,而使用ASCII对这些人来说无疑是不考虑的,除此之外,他正在关闭自己的软件,以适应一个庞大且不断增长的经济。好的。

因此,需要一个包含所有语言的包含字符集。Unicode就是这样出现的。它为每个字符分配一个称为码位的唯一数字。Unicode比其他可能的集合的一个优点是,前256个代码点与ISO-8859-1相同,因此也与ASCII相同。此外,在一个称为基本多语言平面(BMP)的区域中,大多数常用字符只能用两个字节表示。现在需要一个字符编码来访问这个字符集,正如问题所问的,我将集中讨论UTF-8和UTF-16。好的。内存注意事项

那么有多少字节可以访问这些编码中的哪些字符呢?好的。

  • UTF-8:
    • 1字节:标准ASCII
    • 2字节:阿拉伯语、希伯来语、大多数欧洲文字(最显著的是不包括格鲁吉亚语)
    • 3字节:BMP
    • 4字节:所有Unicode字符
  • UTF—16:
    • 2字节:BMP
    • 4字节:所有Unicode字符

现在值得一提的是,BMP中没有的汉字包括古代文字、数学符号、音乐符号以及更为罕见的中/日/韩(CJK)汉字。好的。

如果您主要使用的是ASCII字符,那么UTF-8肯定更节省内存。但是,如果您主要使用非欧洲脚本,那么使用UTF-8的内存效率可能比UTF-16低1.5倍。当处理大量文本时,如大型网页或冗长的Word文档,这可能会影响性能。好的。编码基础

注意:如果您知道如何对utf-8和utf-16进行编码,请跳到下一节了解实际应用程序。好的。

  • utf-8:对于标准的ASCII(0-127)字符,utf-8代码是相同的。如果需要向后兼容现有的ASCII文本,这使得UTF-8成为理想的选择。其他字符需要2-4个字节。这是通过在每个字节中保留一些位来完成的,以指示它是多字节字符的一部分。特别是,每个字节的第一位是1,以避免与ASCII字符冲突。
  • UTF-16:对于有效的BMP字符,UTF-16表示只是其代码点。但是,对于非BMP字符,UTF-16引入了代理项对。在这种情况下,两个双字节部分的组合映射到非BMP字符。这两个字节部分来自BMP数字范围,但Unicode标准保证其作为BMP字符无效。此外,由于UTF-16有两个字节作为其基本单位,因此它受endianness的影响。为了进行补偿,可以将保留的字节顺序标记放在数据流的开头,该数据流指示结束符。因此,如果您正在读取UTF-16输入,并且没有指定endianness,则必须检查这一点。

可以看出,utf-8和utf-16之间根本不兼容。因此,如果您正在进行I/O,请确保您知道您使用的是哪种编码!有关这些编码的更多详细信息,请参阅UTF常见问题解答。好的。实用程序设计注意事项

字符和字符串数据类型:它们是如何在编程语言中编码的?如果它们是原始字节,当您尝试输出非ASCII字符时,可能会遇到一些问题。此外,即使字符类型基于UTF,也不意味着字符串是正确的UTF。它们可能允许非法的字节序列。一般来说,您必须使用支持UTF的库,例如ICU,用于C、C++和Java。在任何情况下,如果要输入/输出默认编码以外的内容,必须先转换它。好的。

推荐/默认/主要编码:当选择要使用哪种UTF时,对于您所处的环境,通常最好遵循推荐的标准。例如,UTF-8在Web上占主导地位,而且自HTML5以来,它一直是推荐的编码方式。相反,.NET和Java环境都建立在UTF16字符类型上。令人困惑的是(并且不正确地),经常引用"Unicode编码",这通常是指给定环境中的主要UTF编码。好的。

库支持:您使用支持的库有哪些编码?他们支持角箱吗?由于必要性是发明之母,因此UTF-8库通常正确地支持4字节字符,因为1、2甚至3字节字符可能经常出现。然而,并非所有据称的UTF-16库都正确地支持代理对,因为它们很少出现。好的。

计数字符:Unicode中存在组合字符。例如,代码点U+006E(N)和U+0303(组合颚化符)形式为N&x303;,但代码点U+00F1形式为&xf1;。它们看起来应该相同,但是一个简单的计数算法将在第一个示例中返回2,在后一个示例中返回1。这并不一定是错误的,但也可能不是期望的结果。好的。

比较是否平等:&x41;、&x410;、和&x391;看起来相同,但它们分别是拉丁语、西里尔文和希腊语。您还可以使用&x43;和&x216d;等大小写,一个是字母,另一个是罗马数字。此外,我们还需要考虑组合字符。有关详细信息,请参阅Unicode中的重复字符。好的。

代理对:这些经常出现,所以我将提供一些示例链接:好的。

  • 获取字符串长度
  • 移除代理项对
  • 回文检查

其他?:好的。好啊。


  • 统一码
    • 是全世界使用的一组字符
  • UTF-8
    • 能够用Unicode编码所有可能的字符(称为码位)的字符编码。
    • 代码单位为8位
    • 使用一到四个代码单位编码Unicode
    • 00100100表示"$"(一个8位);11000010 101000110表示"美分"(两个8位);11100010 10000010 10101100表示"欧元"(三个8位)
  • UTF 16
    • 另一个字符编码
    • 代码单位为16位
    • 使用一到两个代码单位编码Unicode
    • 00000000 00100100表示"$"(一个16位);11011000 01010010 11011111 01100010表示"??"(两个16位)


Unicode is a fairly complex standard. Don’t be too afraid, but be
prepared for some work! [2]

由于总是需要可靠的资源,但官方报告是巨大的,我建议阅读以下内容:

  • 绝对最小值每个软件开发人员绝对,肯定必须知道Unicode和字符集(没有借口!)Stack Exchange首席执行官Joel Spolsky的介绍。
  • 去BMP和其他地方!埃里克·穆勒(EricMuller),当时的技术总监,后来的副总裁,在Unicode联盟(Unicode Consortium)做了一个教程。(前20张幻灯片完成)
  • 简要说明:

    计算机读取字节,人们读取字符,所以我们使用编码标准将字符映射到字节。ASCII是第一个广泛使用的标准,但只涵盖拉丁语(7位/字符可以代表128个不同的字符)。Unicode是一种标准,其目标是覆盖世界上所有可能的字符(最多可容纳1114112个字符,即21位/字符。当前的Unicode 8.0总共指定了120737个字符,仅此而已)。

    主要的区别是一个ASCII字符可以适合一个字节(8位),但大多数Unicode字符不能。因此,使用编码形式/方案(如utf-8和utf-16),字符模型如下所示:

    每个字符都拥有一个从0到1114111(十六进制:0-10ffff)的被称为码位的枚举位置。编码表单将代码点映射到代码单元序列。代码单元是您希望在内存、8位单元、16位单元等中组织字符的方式。UTF-8使用1到4个8位的单位,而UTF-16使用1或2个16位的单位来覆盖整个Unicode(最多21位)。单位使用前缀以便可以发现字符边界,更多的单位意味着占用位的前缀更多。因此,尽管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位,所以两位十六进制数字代表一个字节还可以看看维基百科的平面图,了解一下字符集的布局。


    最初,Unicode的目标是采用固定宽度的16位编码(ucs-2)。Unicode的早期采用者,如Java和Windows NT,围绕16位字符串构建了它们的库。

    后来,Unicode的范围被扩展到包含历史字符,这将需要16位编码支持的65536个代码点。为了允许在使用了UCS-2的平台上表示额外的字符,引入了UTF-16编码。它使用"代理对"来表示补充平面中的字符。

    同时,许多旧的软件和网络协议都使用8位字符串。UTF-8是为了使这些系统能够支持Unicode而不必使用宽字符。它与7位ASCII向后兼容。


    这篇文章解释了所有的细节http://kunststube.net/编码/

    写入缓冲区

    如果您使用UTF8编码写入4字节缓冲区(符号),那么您的二进制文件将如下所示:

    00000000 11100011 10000001 1000000

    如果用UTF16编码写入一个4字节的缓冲区(符号,则二进制文件将如下所示:

    00000000 00000000 00110000 01000010

    如你所见,根据你在内容中使用的语言,这将相应地影响你的记忆。

    例如,对于这个特殊的符号:utf16编码更有效,因为我们有2个备用字节用于下一个符号。但这并不意味着你必须在日本字母表中使用UTF16。

    从缓冲区读取

    现在,如果你想读取上面的字节,你必须知道它是用什么编码写的,然后正确地将它解码回来。

    例如,如果您对此进行解码:00000000 11100011 10000001 1000000在UTF16编码中,您将以而不是结束。

    注意:编码和Unicode是两个不同的东西。Unicode是一个大(表),每个符号映射到一个唯一的代码点。例如,符号(字母)有一个(代码点):30 42(十六进制)。另一方面,编码是一种在存储到硬件时将符号转换为更合适方式的算法。

    1
    2
    3
    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.

    enter image description here


    为什么是Unicode?因为ASCII只有127个字符。128到255个不同的国家有不同的代码页,这就是为什么有代码页。所以他们说我们最多有1114111个字符。那么,如何存储最高的代码点呢?您将需要使用21位来存储它,所以您将使用一个32位的dword,其中11位被浪费。因此,如果使用双字来存储Unicode字符,这是最简单的方法,因为双字中的值正好与代码点匹配。但双字数组当然比字数组大,当然甚至比字节数组大。这就是为什么不仅有UTF-32,而且还有UTF-16。但是,utf-16意味着一个字流,一个字有16个位,那么最高的代码点1114111如何能适合一个字呢?它不能!所以他们把每一个高于65535的值放入一个他们称之为代理项对的双字中。这样的代理对是两个单词,可以通过查看前6位来检测。那么UTF-8呢?它是一个字节数组或字节流,但是最高的代码点1114111如何能适应一个字节?它不能!好吧,所以他们也放了一个双字,对吗?或者可能是一句话,对吧?几乎是对的!他们发明了UTF-8序列,这意味着每一个高于127的码位都必须被编码成2字节、3字节或4字节的序列。真的!但是我们如何检测这些序列呢?好吧,127之前的所有东西都是ASCII码,并且是单字节的。以110开头的是两字节序列,以1110开头的是三字节序列,以11110开头的是四字节序列。这些所谓的"startbytes"的剩余位属于代码点。现在,根据顺序,必须遵循以下字节。下一个字节以10开头,其余的位是有效负载位的6位,属于码位。连接startbyte的有效负载位和下面的byte/s,您将得到代码点。这就是UTF-8的魔力所在。


    Unicode是一种标准,它将所有语言中的字符映射到称为代码点的特定数值。这样做的原因是,它允许使用同一组代码点进行不同的编码。

    UTF-8和UTF-16是这两种编码。它们将代码点作为输入,并使用一些定义良好的公式对其进行编码,以生成编码的字符串。

    选择特定的编码取决于您的需求。不同的编码有不同的内存需求,根据您将要处理的字符,您应该选择使用最少字节序列来编码这些字符的编码。

    有关unicode、utf-8和utf-16的更深入的详细信息,您可以签出本文,

    每个程序员都应该知道什么是Unicode


    ASCII-软件只为给定字符在内存中分配8位字节。它适用于英语和被采用的语言(如fa?ade)字符的对应十进制值在十进制值中低于128。示例C程序。

    utf-8-软件为给定字符分配1到4个变量8位字节。这里的变量是什么意思?假设您通过浏览器中的HTML页面发送字符"A"(HTML为UTF-8),A的对应十进制值为65,当您将其转换为十进制时,它将变为01000010。这只需要1个字节,即使是像'?'这样的特殊采用的英文字符,也会分配1个字节的内存。总之,FA?艾德。但是,当您想要存储欧洲字符时,它需要2个字节,所以您需要UTF-8。但是,当您使用中文字符时,需要至少2个字节,最多4个字节。同样,emoji需要3到4个字节。UTF-8可以满足您的所有需求。

    UTF-16将为每个字符分配至少2个字节和最多4个字节,而不会分配1或3个字节。每个字符可以用16位或32位表示。

    那么为什么存在UTF-16呢?最初,Unicode是16位而不是8位。Java采用了原始版本的UTF 16。

    简而言之,您不需要在任何地方使用UTF-16,除非它已经被您所使用的语言或平台所采用。

    Web浏览器调用的Java程序使用UTF-16,但是Web浏览器使用UTF-8发送字符。


    utf代表unicode转换格式。在当今世界,基本上有数百种其他语言编写的脚本,这些格式没有被前面使用的基本ASCII所覆盖。因此,UTF应运而生。

    UTF-8具有字符编码能力,其编码单元为8位,而UTF-16的编码单元为16位。