Qt 5 编码问题(UTF-8、Windows-1250、Windows-1251)

kil*_*ick 3 c++ utf-8 character-encoding qt4.8 qt5

我所有的源文件都是UTF-8转换的。

\n\n

我打开的所有文件都是 UTF-8。

\n\n

我的应用程序正在打开 UTF-8 编码文件,其中包含 3 种语言的翻译文本:英语、波兰语和俄语,并将数据保存到文件中,分为 3 个单独的编码块:Windows-1250(英语)、Windows-1250(波兰语)和Windows-1251(俄语)- 是的,没错,我在一个文件中混合编码类型,然后由知道如何处理该文件的第三方设备使用。

\n\n

Iv 得到了一个在 Qt4 下完美运行的测试程序,现在当我转移到 Qt5 时它停止运行(文本保存为 ?????????):

\n\n
    \n
  • 测试编码.cpp

    \n\n
    test_encoding::test_encoding(QWidget *parent) : QMainWindow(parent)\n{\n  ui.setupUi(this);\n\n  QString d;\n  QFile f(QDir::currentPath() + "/input.txt");\n  if( f.open( QIODevice::ReadOnly | QIODevice::Text ) )\n  {\n    d = f.readAll();\n    f.close();\n  }\n\n  QFile ff(QDir::currentPath() + "/output.txt");\n  if( ff.open( QIODevice::WriteOnly | QIODevice::Text ) )\n  {\n    QTextStream t(&ff);\n    auto cutf8 = QTextCodec::codecForName("UTF-8");\n    auto cw50 = QTextCodec::codecForName("windows-1250");\n    auto cw51 = QTextCodec::codecForName("windows-1251");\n\n        // ____Block 1\n    t.setCodec(cutf8);\n    t << d << "\\r\\n";\n    t << cutf8->fromUnicode(d) << "\\r\\n";\n    t.flush();\n\n        // ____Block 2\n    t.setCodec(cw50);\n    t << d << "\\r\\n";\n    t << cw50->fromUnicode(d) << "\\r\\n";\n    t.flush();\n\n        // ____Block 3\n    t.setCodec(cw51);\n    t << d << "\\r\\n";\n    t << cw51->fromUnicode(d) << "\\r\\n";\n    t.flush();\n  }\n  ff.close();\n\n  QCoreApplication::quit();\n}\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
  • input.txt(UTF-8 无 BOM)

  • \n
\n\n
\n

U\xc5\xbcytkownik niezalogowany

\n\n

未登录用户

\n\n

\xd0\x9d\xd0\xb5 \xd0\xb7\xd0\xb0\xd1\x80\xd0\xb5\xd0\xb3\xd0\xb8\xd1\x81\xd1\x82\xd1\x80\xd0\xb8\xd1 \x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xbd\xd1\x8b\xd0\xb9

\n
\n\n
    \n
  • output.txt(多代码页块)
  • \n
\n\n
\n

____区块 1:

\n\n

U\xc5\xbcytkownik niezalogowany

\n\n

未登录用户

\n\n

\xd0\x9d\xd0\xb5 \xd0\xb7\xd0\xb0\xd1\x80\xd0\xb5\xd0\xb3\xd0\xb8\xd1\x81\xd1\x82\xd1\x80\xd0\xb8\xd1 \x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xbd\xd1\x8b\xd0\xb9

\n\n

U\xc5\xbcytkownik niezalogowany

\n\n

未登录用户

\n\n

\xd0\x9d\xd0\xb5 \xd0\xb7\xd0\xb0\xd1\x80\xd0\xb5\xd0\xb3\xd0\xb8\xd1\x81\xd1\x82\xd1\x80\xd0\xb8\xd1 \x80\xd0\xbe\xd0\xb2\xd0\xb0\xd0\xbd\xd0\xbd\xd1\x8b\xd0\xb9

\n\n

____区块 2:

\n\n

U\xe0\xa0\xb9tkownik niezalogowany

\n\n

未登录用户

\n\n

?? ??????????????????

\n\n

U?ytkownik niezalogowany

\n\n

未登录用户

\n\n

?? ??????????????????

\n\n

____区块 3:

\n\n

U\xe0\xa0\xb9tkownik niezalogowany

\n\n

未登录用户

\n\n

?? ??????????????????

\n\n

U?ytkownik niezalogowany

\n\n

未登录用户

\n\n

?? ??????????????????

\n
\n\n

看来只能将文本保存为 UTF-8,这不适合我 - 我需要使用代码页 Windows-1251 和 Windows-1250。

\n\n

Qt5 是否可以从 UTF-8 转换为其他代码页?

\n

kil*_*ick 5

Iv 向 Qt 报告了 Qt 5 中的一个错误: https: //bugreports.qt.io/browse/QTBUG-42498

目前的解决方法是每次想要更改代码页时创建一个新的 QTextStream 对象 - 在执行 QTextStream::flush() 后,不可能使用 QTextStream::setCodec() 更改代码页 - 检查上面链接中的错误描述。问题出在 QIcuCodec::getConverter() 源代码的第 5 行 - http://pastebin.com/2dEcCyET

因此,在 Qt 5 中不起作用(但在 Qt 4.8.4 中起作用)的代码是这样写的:

QFile f;
QTextStream ts(&f);
ts.setCodec("Windows-1250");
ts << englishTranslationBlock();
ts << polishTranslationBlock();
ts.flush();
ts.setCodec("Windows-1251");
ts << russianTranslationBlock();
ts.flush();
f.close();
Run Code Online (Sandbox Code Playgroud)

要解决报告的错误,代码必须创建一个新的 QTextStream 以允许更改编解码器。当这样写时,代码将起作用:

QFile f;
QTextStream* ts = new QTextStream(&f);
ts->setCodec("Windows-1250");
ts << englishTranslationBlock();
ts << polishTranslationBlock();
ts->flush();
delete ts;
ts = new QTextStream(&f);
ts->setCodec("Windows-1251");
ts << russianTranslationBlock();
ts->flush();
f.close();
Run Code Online (Sandbox Code Playgroud)