Unicode,UTF-8,UTF-16和UTF-32问题

时间:2014-06-30 18:18:21

标签: c++ unicode utf-8 utf-16 utf-32

我读了很多关于Unicode,ASCII,代码页,所有历史,UTF-8,UTF-16(UCS-2),UTF-32(UCS-4)的发明以及使用它们的人等等,但我仍然有一些问题,我试图找不到答案,但我不能,我希望你能帮助我。

1 - Unicode是编码字符的标准,它们为每个字符指定代码点。比如U + 0000(例子)。想象一下,我有一个包含这些代码点的文件(\ u0000),在我的应用程序中,我将使用它吗?

这可能是一个愚蠢的问题,但我真的不知道我将在哪个应用程序中使用它。 我正在创建一个应用程序,可以使用转义\u读取具有这些代码点的文件,我知道我可以读取它,解码它但现在是下一个问题。

2 - 转换到哪个字符集(代码页)?我看到一些C ++库,他们使用名称utf8_to_unicodeutf8-to-utf16,也只使用utf8_decode,这让我感到困惑。

我不知道是否会出现这样的答案,但有些人可能会说:您需要将其转换为您将要使用的代码页,但如果我的应用程序需要国际化呢?

3 - 我想知道,在C ++中,如果我尝试在终端上显示非ASCII字符,我会得到一些令人困惑的单词。问题是:显示字符的原因是字体?

#include <iostream>

int main()
{
    std::cout << "ö" << std::endl;

    return 0;
}

输出(Windows):

  

├Â

4 - 编码进入该过程的哪个部分?它编码,获取代码点并尝试找到字体上相同的单词?

5 = WebKit是一个用于在Web浏览器中呈现网页的引擎,如果您将字符集指定为UTF-8,它可以很好地与所有字符一起使用,但是如果我指定另一个字符集则不会,则不会重要的是我正在使用的字体,会发生什么?

<html>
<head>
    <meta charset="iso-8859-1"> 
</head>
<body>
    <p>ö</p>
</body>
</html>

输出:

  

ö

使用:

<meta charset="utf-8">

6 - 想象一下,现在我读了文件,我编码了,我有所有的代码点,我需要再次保存文件。我是否需要保存编码(\ u0000)或者我需要首先解码才能再次转换为字符然后保存?

7 - 为什么单词“unicode”有点过载,有时被理解为utf-16? (source

这就是现在。提前谢谢。

1 个答案:

答案 0 :(得分:1)

  

我正在创建一个应用程序,可以使用escape \ u读取具有这些代码点的文件,我知道我可以读取它,解码它但现在是下一个问题。

如果您正在编写一个处理某种自定义转义的程序,例如\uXXXX,则完全取决于您何时将这些转义转换为Unicode代码点。

  

我需要将哪个字符集(代码页)转换成它?

这取决于你想做什么。如果您正在使用其他需要特定代码页的库,那么您可以将数据从一个编码转换为该库所需的编码。如果您没有此类第三方图书馆的任何硬性要求,则可能没有理由进行任何转换。

  

我想知道,在C ++中,如果我尝试在终端上显示非ASCII字符,我会得到一些令人困惑的词语。

这是因为技术堆栈的各个层使用不同的编码。从您给出的示例输出"├Â"我可以看到正在发生的事情是您的编译器将字符串文字编码为UTF-8,但控制台正在使用Windows代码页850.通常当控制台存在编码问题时您可以通过将控制台输出代码页设置为正确的值来修复它们,不幸的是,通过std::cout传递UTF-8目前存在一些独特的问题。在VS2012中使用printf代替了我:

#include <cstdio>
#include <Windows.h>

int main() {
    SetConsoleOutputCP(CP_UTF8);
    std::printf("%s\n", "ö");
}

希望Microsoft修复C ++库,如果他们还没有在VS 14中这样做。

  

编码进入该过程的哪一部分?它编码,获取代码点并尝试找到字体上相同的单词?

除非您知道编码,否则数据字节无意义。因此,编码在流程的所有部分都很重要。

我不明白这里的第二个问题。

  

如果你将字符集指定为UTF-8,它可以很好地与所有字符一起使用,但是如果我指定另一个字符集则没有,那与我使用的字体无关,会发生什么?

这里发生的是当您编写charset="iso-8859-1"时,您还必须将文档实际转换为该编码。你没有这样做,而是将文档保留为UTF-8编码。

作为一个小练习,假设我有一个包含以下两个字节的文件:

0xC3 0xB6

使用有关UTF-8编码和解码的信息,字节解码到哪个代码点?

现在使用this 8859-1 codepage,相同的字节解码到什么?

另一项练习是保存HTML文档的两个副本,一个使用charset="iso-8859-1",另一个使用charset="utf-8"。现在使用十六进制编辑器检查两个文件的内容。

  

想象一下,我现在读取文件,编码它,我有所有代码点,我需要再次保存文件。我是否需要保存编码(\ u0000)或者我需要首先解码才能再次转换为字符然后保存?

这取决于需要读取文件的程序。如果程序希望所有非ASCII字符都像那样转义,那么你必须以这种方式保存文件。但使用\u转义字符不是正常的事情。我只在一些地方看到过这种情况,例如JSON数据和C ++源代码。

  

为什么单词“unicode”有点过载,有时被理解为utf-16?

主要是因为微软以这种方式使用这个术语。他们出于历史原因这样做:当他们添加Unicode支持时,他们命名所有选项并设置“Unicode”,但他们支持的唯一编码是UTF-16。