【问题标题】:QString - UTF8 embedded in 16Bits?QString - UTF8 嵌入 16 位?
【发布时间】:2015-12-03 11:34:30
【问题描述】:

我很惊讶。我开始深入研究QString::data(),同时试图帮助这里的另一个提问者解决 QString 与 ASCII 相关的问题。

我制作了以下代码,它查看每 16 位 QString 数据包,发现像“ä”和“ß”这样的字母似乎以 UTF-8 编码,但使用 16 位来存储 8 位.当然,他们可以随心所欲,但文档说 QString 将采用 UTF-16。但对我来说它看起来不同。

更正: Qt 4.8 的 QString 文档并没有真正提到 UTF-16。 但它也没有说明 UTF-8 与 16 位一起使用。

拜托,谁能赐教!?

我的代码:

QString h("AßB");

char * pt = (char*)h.data();

for(int i = 0; ;i+=2) {

   // get 16bit value
   u_int16_t s = *(u_int16_t*)(pt + i);

   // break condition
   if(s == 0) break;

   qDebug() << i << s << QChar(s) << h.size();
}

qDebug() 告诉我什么:

0 65 'A' 4 
2 195 'Ã' 4 
4 159 '' 4 
6 66 'B' 4 

请注意,“ß”似乎是 UTF-8 编码的,但在编码的两个部分仍然使用 16 位。

195 159 是 'ß' 的 UTF-8 编码。

我的字符映射告诉我 'ß' 的 UTF-16 表示应该是 0x00DF。这就是我希望得到的。

另请注意,QString::size() 报告的可疑大小为 4 而不是 3。

【问题讨论】:

  • 您使用的是哪个操作系统和 Qt 版本?
  • @Meefte Qt 4.8 和 Debian 8 (Jessie)。你有其他结果吗?
  • 我在 Windows 7 和 Qt 5.5 上获得了 0 65 'A' 3 | 2 223 '00\u00df' 3 | 4 66 'B' 3
  • 字符串文字中的非 ASCII 字符不可移植。不要假设它们会在您的系统中按您期望的那样工作。特别是,您的系统可能使用 UTF-8 进行源编码,但 Qt 在其构造函数中使用 fromAscii
  • 避免源文件编码问题 n.m.提到,尝试使用QString h = QString::fromLatin1("A\337B"),它可以避免非ascii文字并进行从latin1到QString的显式转换。

标签: c++ qt


【解决方案1】:

QString 数据在内部存储为 Unicode。来自 qt 文档:

QString str = "Hello";

“QString 使用 fromUtf8() 函数将 const char * 数据转换为 Unicode。”

这是链接:QString Class

奇怪的是,我没有看到任何 toUTF16() 方法;虽然它确实有一个 toUTF8。

另外,UTF-16 不是 Unicode:

“Unicode 标准对 U+0000..U+10FFFF 范围内的字符进行编码,相当于 21 位代码空间。取决于您选择的编码形式(UTF-8、UTF-16 或 UTF- 32),然后每个字符将被表示为一到四个 8 位字节、一个或两个 16 位代码单元或单个 32 位代码单元的序列。"

发件人:Frequently Asked Questions - UTF-8, UTF-16, UTF-32 & BOM

编辑:

我知道 MSVC 曾经用于编译 Unicode 和非 Unicode 版本。来自 M$:

"Unicode UTF-16 编码

将 Unicode 字符表示为 16 位整数序列。您的应用程序可以使用 UnicodeEncoding 类将字符与 UTF-16 编码相互转换。

UTF-16 通常在本地使用,如 Microsoft.Net char 类型、Windows WCHAR 类型和其他常见类型。最常见的 Unicode 代码点仅使用一个 UTF-16 代码点(2 个字节)。 Unicode 补充字符 U+10000 和更大的字符仍然需要两个 UTF-16 代理代码点。”

发现于.NET Framework 3.5 - Using Unicode Encoding

因此,M$ 在内部经常使用 UTF-16。 Unicode 是 21 位长的符号列表,有多种 UTF 格式对其进行编码。

这对您在 Ubuntu 上有何影响? M$ 在内部用 UTF-16 对事物进行编码,并称它们为 Unicode。

Frank Osterfeld 显然在您的代码中发现了问题:编译器正在使用源文件的编码来生成字符串文字。奇怪的是它使用了 16 位编码,并得出了 UTF-8 值;从而得出错误的字符序列!如果您打印出 QString,我想知道它是否会显示为带有变音符号的“A”。尽管编译器显然不理解它,但它可能在您看到它之前就被转换回相同的 UTF-8。 Frank 和你已经能够证明在 Ubuntu 上,Qt 使用 UTF-16。似乎在未编码(即 21 位)的计算机数据中几​​乎看不到 Unicode 字符。 “Unicode”构建显然是 UTF-16 构建。

【讨论】:

  • “另外,UTF-16 不是 Unicode”是什么意思?
  • 根据引用,Unicode 是 21 位。 UTF-16 是 16。至于 Qt 是使用全部 21 位还是仅使用 16 位,我不能肯定。这或许可以解释 Aaron 的奇怪结果。
  • Unicode 不是任何位。它只是为字符分配数字。 UTF-16 以 16 位代码单元定义了这些数字的编码。但是,它确实需要至少 21 位来表示所有 Unicode,而 UTF-16 允许一个或两个代码单元(2 或 4 个字节)对单个 Unicode 代码点进行编码。
  • 我个人觉得这个talk 很有趣,但是只看specs,你会发现UTF-16 是Unicode 编码形式之一(恕我直言,最糟糕,但仍然是一部分的标准)。
  • 我想知道是否可能是这种情况。但是,我想如果他们只是将它们称为 UTF-16 构建而不是 Unicode 构建,那么混淆就会减少。我已经知道 Qt 已经在内部将其存储为 Unicode,但我不知道它是 UTF-16,至少在 Linux 中,显然在 WINdows 上。在知道它在内部存储为 Unicode 之前,我和你们一起发现了自己。
猜你喜欢
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
  • 2012-05-01
  • 1970-01-01
  • 2014-05-25
  • 2011-01-30
  • 1970-01-01
相关资源
最近更新 更多