检测文本文件的编码格式。

5

在我的程序中,我加载用户提供的纯文本文件:

QFile file(fileName);
file.open(QIODevice::ReadOnly);
QTextStream stream(&file);
const QString &text = stream.readAll();

当文件采用UTF-8编码时,此方法运作良好。但是一些用户试图导入采用Windows-1252编码的文件,如果这些文件中包含有特殊字符的单词(例如“boutonnière”中的“è”),则会显示出现问题。

是否有一种方法可以检测编码,或至少区分UTF-8(可能没有BOM)和Windows-1252,而不必要求用户告诉我编码方式?


我真的很抱歉,纯文本文件的诅咒。快速的谷歌搜索也证实了这一点:http://qt-project.org/forums/viewthread/12619 - Mattsjo
尝试解码文本为UTF-8格式,如果失败则不是UTF-8。 - Kerrek SB
3
怎么知道它失败了? - sashoalm
@Mattsjo 是的,在发布问题之前我已经阅读过了。第二部分怎么样——只是区分UTF-8和Windows-1252?那可能吗?顺便说一句,我知道Notepad++可以做到这一点,但他们可能为此编写了很多代码。 - sashoalm
我的意思是使用标准的Qt函数从字节数组中获取一个QString,该字节数组可能具有有效的UTF-8文本,也可能没有。那么我如何知道它失败了?例如QString :: fromUtf8()不会返回成功或失败,而是会默默地替换任何无效的序列。 - sashoalm
显示剩余2条评论
2个回答

4

这个技巧对我来说很有效,至少目前为止是这样的。这种方法不需要BOM即可发挥作用:

    QTextCodec::ConverterState state;
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    const QByteArray data(readSource());
    const QString text = codec->toUnicode(data.constData(), data.size(), &state);
    if (state.invalidChars > 0)
    {
        // Not a UTF-8 text - using system default locale
        QTextCodec * codec = QTextCodec::codecForLocale();
        if (!codec)
           return;

        ui->textBrowser->setPlainText(codec->toUnicode(readSource()));
    }
    else
    {
        ui->textBrowser->setPlainText(text);
    }

4

事实证明,对于一般情况而言,自动检测编码是不可能的。

然而,至少有一个解决方法可以在文本无法识别为UTF-8/UTF-16/UTF-32时回归到系统语言环境。它使用了QTextCodec::codecForUtfText(),该方法在尝试使用UTF-8、UTF-16和UTF-32解码字节数组失败后返回提供的默认编解码器。

实现代码如下:

QTextCodec *codec = QTextCodec::codecForUtfText(byteArray, QTextCodec::codecForName("System"));
const QString &text = codec->toUnicode(byteArray);

更新

上述代码将无法检测UTF-8无BOM的文本,因为codecForUtfText()依赖于BOM标记。要检测没有BOM的UTF-8,请参阅https://dev59.com/G2Ml5IYBdhLWcg3wqIdh#18228382


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接