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

在VSS中,当进行文件比较时,有时会有一个消息说两个文件有不同的UTF。为什么会这样呢?

请简单解释一下。


当前回答

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

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

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

有关Unicode, UTF-8和UTF-16的更多详细信息,您可以查看这篇文章,

关于Unicode,每个程序员都应该知道的

其他回答

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

后来,Unicode的范围扩大到包括历史字符,这将需要超过16位编码所支持的65,536个编码点。为了允许在使用UCS-2的平台上表示额外的字符,引入了UTF-16编码。它使用“代理对”来表示补充平面中的字符。

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

为什么我们需要统一码?

在(不是太)早期,所有存在的都是ASCII。这是可以的,因为所需要的只是一些控制字符、标点符号、数字和字母,就像这句话中的这些。不幸的是,今天这个全球相互交流和社交媒体的陌生世界并没有被预见到,在同一份文件中看到英文、العربية、汉语、ְִרִי、ελληνικ和ភាសាខ្មែរ也不是太罕见(希望我没有弄坏任何旧浏览器)。

但是为了讨论,让我们假设Joe Average是一个软件开发人员。他坚持说他永远只需要英语,因此他只想使用ASCII码。这对用户Joe来说可能没问题,但对软件开发人员Joe来说就不好了。世界上大约有一半的人使用非拉丁字符,使用ASCII可能是对这些人的不体贴,最重要的是,他正在将他的软件向一个庞大的、不断增长的经济体关闭。

Therefore, an encompassing character set including all languages is needed. Thus came Unicode. It assigns every character a unique number called a code point. One advantage of Unicode over other possible sets is that the first 256 code points are identical to ISO-8859-1, and hence also ASCII. In addition, the vast majority of commonly used characters are representable by only two bytes, in a region called the Basic Multilingual Plane (BMP). Now a character encoding is needed to access this character set, and as the question asks, I will concentrate on UTF-8 and 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: For the standard ASCII (0-127) characters, the UTF-8 codes are identical. This makes UTF-8 ideal if backwards compatibility is required with existing ASCII text. Other characters require anywhere from 2-4 bytes. This is done by reserving some bits in each of these bytes to indicate that it is part of a multi-byte character. In particular, the first bit of each byte is 1 to avoid clashing with the ASCII characters. UTF-16: For valid BMP characters, the UTF-16 representation is simply its code point. However, for non-BMP characters UTF-16 introduces surrogate pairs. In this case a combination of two two-byte portions map to a non-BMP character. These two-byte portions come from the BMP numeric range, but are guaranteed by the Unicode standard to be invalid as BMP characters. In addition, since UTF-16 has two bytes as its basic unit, it is affected by endianness. To compensate, a reserved byte order mark can be placed at the beginning of a data stream which indicates endianness. Thus, if you are reading UTF-16 input, and no endianness is specified, you must check for this.

可以看到,UTF-8和UTF-16彼此完全不兼容。所以如果你在做I/O,确保你知道你在使用哪种编码!有关这些编码的进一步细节,请参阅UTF常见问题解答。

实际编程注意事项

Character and string data types: How are they encoded in the programming language? If they are raw bytes, the minute you try to output non-ASCII characters, you may run into a few problems. Also, even if the character type is based on a UTF, that doesn't mean the strings are proper UTF. They may allow byte sequences that are illegal. Generally, you'll have to use a library that supports UTF, such as ICU for C, C++ and Java. In any case, if you want to input/output something other than the default encoding, you will have to convert it first.

Recommended, default, and dominant encodings: When given a choice of which UTF to use, it is usually best to follow recommended standards for the environment you are working in. For example, UTF-8 is dominant on the web, and since HTML5, it has been the recommended encoding. Conversely, both .NET and Java environments are founded on a UTF-16 character type. Confusingly (and incorrectly), references are often made to the "Unicode encoding", which usually refers to the dominant UTF encoding in a given environment.

库支持:您正在使用的库支持某种编码。哪一个?他们支持极端情况吗?因为需要是发明之母,UTF-8库通常会正确地支持4字节字符,因为1、2甚至3字节字符经常出现。然而,并不是所有的UTF-16库都正确地支持代理对,因为它们很少出现。

字符计数:Unicode中存在组合字符。例如,代码点U+006E (n)和U+0303(一个组合波浪号)组成ñ,而代码点U+00F1组成ñ。它们看起来应该是相同的,但是一个简单的计数算法将为第一个示例返回2,为后一个示例返回1。这并不一定是错误的,但也可能不是理想的结果。

平等比较:A、А和Α看起来一样,但它们分别是拉丁语、西里尔语和希腊语。你也有C和Ⅽ这样的情况。一个是字母,另一个是罗马数字。此外,我们还需要考虑组合字符。有关更多信息,请参见Unicode中的重复字符。

代理对:这些在Stack Overflow中经常出现,所以我只提供一些示例链接:

获取字符串长度 删除代理对 回文检查

文章什么每个程序员绝对,积极地需要知道编码和字符集来处理文本解释了所有的细节。

写入缓冲区

如果你写入一个4字节的缓冲区,符号あUTF8编码,你的二进制将看起来像这样:

00000000 11100011 10000001 10000010

如果你写入一个4字节的缓冲区,使用UTF16编码的符号あ,你的二进制将看起来像这样:

00000000 00000000 00110000 01000010

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

示例:对于这个特定的符号:あUTF16编码更有效,因为我们有2个空闲字节用于下一个符号。但这并不意味着你必须使用UTF16来表示日本字母。

从缓冲区读取

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

例:如果你解码这个: 00000000 11100011 10000001 10000010 转换为UTF16编码,你将得到臣而不是あ

注意:Encoding和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.

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

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

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

有关Unicode, UTF-8和UTF-16的更多详细信息,您可以查看这篇文章,

关于Unicode,每个程序员都应该知道的

UTF代表Unicode转换格式。基本上,在当今世界,有数百种其他语言编写的脚本,这些脚本的格式不包括在以前使用的基本ASCII中。因此,UTF应运而生。

UTF-8具有字符编码功能,其代码单位为8位,而UTF-16为16位。