【问题标题】:How Utf-8 may not work in Qt 5?utf-8 如何在 Qt 5 中不起作用?
【发布时间】:2018-07-20 05:15:18
【问题描述】:

我有一个原始测试:msvc2015 和 Qt5.9.3 中的项目。 文件main.cpp 以 Unicode 格式保存为带有签名的 UTF-8:

我尝试显示应该显示一些俄语文本的消息框。整个代码:

#include <QtWidgets/QApplication>
#include <QMessageBox>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString ttl = QString::fromUtf8("russian_word_1");
    QString txt = QString::fromUtf8("russian_word_2");

    QMessageBox::information(nullptr, ttl, txt);

    return a.exec();
}

我收到了什么:

这怎么可能?


更新 1: 我想在 BOM according to the Stackoverflow author's statement: 中使用 UTF-8

...在不知道是什么的情况下拥有一个字符串是没有意义的 它使用的编码 ���


更新 2: 在这种特殊情况下,很可能是编译器中的错误。

【问题讨论】:

  • 顺便说一句,请确保您将应用程序编译为 unicode 和/或您的操作系统配置为使用俄语作为非 unicode 程序的默认语言。
  • 我使用 VS2012,Qt 5.6,代码保存为“UTF-8 without BOM”,我可以在 QMessageBoxes 中显示来自代码的德语变音符号:QMessageBox::information(this, tr("Süß!"), tr("{ÄÊì&amp;78╬aúeKã´YﭛᵴҺϸ̚Ƚ")); - 开箱即用。
  • @MartinHennings 是的,但我在谈论 UTF-8 WITH Bom
  • 应该没什么区别。 Qt5 将所有字符串文字解释为 UTF-8(除非明确告知不要这样做),并且我相信 VisualStudio 会对其进行编码,而不管 BOM 是什么。真正的原因一定在别处。
  • @MartinHennings,我一直在工作WITHOUT BOM,从来没有出现过问题。但今天我决定试试WITH :)

标签: c++ visual-studio qt utf-8 string-literals


【解决方案1】:

不要在您的代码中使用非英语的 ASCII。因为编译取决于编译器、源文件编码等。只写英文文本,用tr("") 包裹。创建翻译文件,加载它们。阅读internalization in qt

Another usefull link.

【讨论】:

  • 你确定这是唯一一种语言程序的最佳解决方案吗?
  • @VladimirBershov 是的,我认为这是唯一的方法。如果您使用的是诸如 Visual Studio 或 QtCreator 之类的 IDE,那么它应该很容易使用。
  • @VladimirBershov 建议使用纯英文字符串并将它们 tr() 转换为您的母语,但 /in practice/ 这也应该有效。所以不,这不一定是只有一种语言程序的最佳解决方案 - 出于多种原因(您需要 lupdate/lrelease/distribute,更难在生产中找到字符串,更难在非母语中传达确切的含义等。 )。
  • @DmitrySazonov ,谢谢,但我确信 Unicode 是一劳永逸地解决问题的关键。每个编译器都应该提供对 Unicode 的全面支持(尤其是使用 BOM)。在代码中只使用 ASCII 并使用翻译文件是非常好的建议,但不是因为这个原因。
  • @VladimirBershov 您需要寻找答案,如何强制 MSVC 正确解释您的源文件。那么它与Qt无关。
【解决方案2】:

如果编译器为具有 BOM 的 UTF-8 源文件生成垃圾字符串,则这是编译器中的错误。但是,首先使用带有 UTF-8 is not recommended 的 BOM。除非您确实有理由,否则不应使用它。

此外,您不需要进行明确的fromUtf8() 转换。你可以这样做:

QString ttl = "russian_word_1";
QString txt = "russian_word_2";

QString 假定字符串文字是 UTF-8。来自documentation

在所有采用 const char * 参数的 QString 函数中,const char * 被解释为以 UTF-8 编码的经典 C 风格 '\0' 终止字符串。

您可以使用QStringLiteral 包装字符串文字作为优化,但这不是必需的。

最后,如果您想将应用程序从俄语翻译成其他语言,您可以使用tr() 包装字符串文字。通常最好使用tr(),以防您以后决定进行翻译。

请注意,在源代码中包含非英语字符串通常没问题。这就是 UTF-8(和一般的 Unicode)的用途。所有现代编译器都支持它。然而,大多数人不屑一顾的是非英语代码

auto индекс = 0; // Please don't.

但非英语的字符串也可以。

【讨论】:

  • 但是 Stackoverflow 作者的这句著名的声明怎么样:关于编码的最重要的事实.. It does not make sense to have a string without knowing what encoding it uses
  • @VladimirBershov 在我们的例子中,我们知道它使用什么编码。它是 UTF-8。
  • 是的,但我说的是全局正确性,我也想在另一个 IDE 中使用我的项目
  • @VladimirBershov BOM 是一个Byte Order M方舟。它指定字节顺序。字节顺序与 UTF-8 无关,使用 BOM 会导致问题。就像 ASCII 文件不需要 BOM 一样,UTF-8 也不需要 BOM。只需使用没有 BOM 的 UTF-8 并告诉您的 IDE 您的文件是 UTF-8 而不是 ASCII。这是最简单的解决方案。
  • @VladimirBershov 好吧,您可以忽略建议。我只是告诉你推荐的方法是什么。
【解决方案3】:

使用QByteArray 作为您的消息文本,然后将其作为 unicode QString 进行显示:

 int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec *codec1 = QTextCodec::codecForName("CP1256");
    // Converted Text:
    QByteArray myLanguage = "لا لا لا لا لا لا لا ";
    QString myLanguage2unicode = codec1->toUnicode(myLanguage);
    // Non converted text:
    QString txt = QString::fromUtf8("لا لا لا لا لا لا لا  ");

      QMessageBox::information(nullptr, myLanguage2unicode, txt);

    return a.exec();
}

以上代码结果:

【讨论】:

  • 这取决于源文件的编码和编译器。文本编解码器不适合。
  • @DmitrySazonov 通常,对于简单的、只有一种语言的程序,如果发现 internalization 成本很高 .. 那么,在编写 非英语 源代码中的文本,文本codecs 是一个很好的解决方案.. 我确实使用它们。
  • @DmitrySazonov,以防万一我们不在同一页面上,请查看我的代码和输出快照,正如我在回答中更新的那样,这里的重点是它有效,而它当然不是便携式...等代码的最佳选择。
  • @DmitrySazonov,查看Post
  • 我认为依赖本地 PC 编码是一种非常糟糕的做法,因为它可能随时更改。至少,源文件应该是 utf8/16/32。
【解决方案4】:

如果您使用 Qt Creator + MSVC 编译器,这可能会对您有所帮助。

TLDR:

  1. 将所有源文件保存为 UTF-8 不带 BOM
  2. 在您的 .pro 文件中添加这一行: QMAKE_CXXFLAGS += /utf-8

完成!

参考:

  1. MSVC compiler flag to Set Source and Executable character sets to UTF-8
  2. Add compiler flag in Qt Creator

【讨论】:

  • 谢谢,但我使用的是 Visual Studio IDE。是的,UTF-8-no-BOM 是 Qt 的最佳选择。
猜你喜欢
  • 2015-03-22
  • 2011-04-07
  • 2018-12-02
  • 1970-01-01
  • 2013-01-29
  • 2013-07-19
  • 2017-01-25
  • 2015-08-06
  • 2019-01-30
相关资源
最近更新 更多