系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、判断txt文件编码格式
  • 二、解决方法
  • 具体使用
  • 三、参考


前言

小弟我在在上一篇Qt中QFile类读取ansi编码格式txt文件,在QTextEdit控件中显示乱码 文章中聊到如何读取ANSI和UFT-8文件,但有个前提是首先知道txt文件的编码格式,如何程序中我们事先不知道txt文件的编码格式那我们怎么做呢?下面我和大家就来聊聊如何判断文件的编码格式

一、判断txt文件编码格式

Qt提供了一个类QTextCodec类,专门用来对字符串进行不同编码方式的转换。
其中重要的两个静态方法是:fromUnicode和toUnicode。
通过这两个静态方法可以将其他类型(如gbk)的字符串转换为utf-8字符串(采用toUnicode),或者将utf-8的字符串转换为其他类型(如gbk)的字符串(采用fromUnicode)。
基本原理是:拿到一定长度的 字节流 然后判断含有哪些 byte 就知道是什么东西了,如果是文本文件,先尝试读前两个字节,看是否是BOM,windows,Qt对字符串默认是采用utf-8编码的,如果要打开gbk的文件,依然采用utf-8编码的话,当然就不识别了,显示就是乱码。
读取txt文件时,很多时候无法获取文件的编码格式.如果直接进行使用,则有可能出现乱码.需要在使用前将其转为Unicode(Qt的默认编码格式). 虽然实际的编码格式种类非常多,但平常主要使用的有GBK与UTF-8两种.可以依次尝试转换,如果转换出现无效字符则认为不是该种编码格式. QString GetCorrectUnicode(const QByteArray &ba) { QTextCodec::ConverterState state; QTextCodec *codec = QText

二、解决方法

enum class EncodingFormat : int
    ANSI = 0,//GBK
    UTF16LE,
    UTF16BE,
    UTF8,
    UTF8BOM,
};
EncodingFormat ProjectWin::FileCharacterEncoding(const QString &fileName)
    //假定默认编码utf8
    EncodingFormat code = EncodingFormat::UTF8;
    QFile file(fileName);
    if (file.open(QIODevice::ReadOnly))
            //读取3字节用于判断
            QByteArray buffer = file.read(3);
            quint8 sz1st = buffer.at(0);
            quint8 sz2nd = buffer.at(1);
            quint8 sz3rd = buffer.at(2);
            if (sz1st == 0xFF && sz2nd == 0xFE)
                code = EncodingFormat::UTF16LE;
            else if (sz1st == 0xFE && sz2nd == 0xFF)
                code = EncodingFormat::UTF16BE;
            else if (sz1st == 0xEF && sz2nd == 0xBB && sz3rd == 0xBF)
                code = EncodingFormat::UTF8BOM;
                //尝试用utf8转换,如果无效字符数大于0,则表示是ansi编码
                QTextCodec::ConverterState cs;
                QTextCodec* tc = QTextCodec::codecForName("utf-8");
                tc->toUnicode(buffer.constData(), buffer.size(), &cs);
                code = (cs.invalidChars > 0) ? EncodingFormat::ANSI : EncodingFormat::UTF8;
            file.close();
    return code;
}

具体使用

void ProjectWin::readParaFile(QString filePath)
//读取ansi编码格式文件
    m_paraText->clear();
    if (!m_paraText) {
        qDebug() << "m_paraText is null!";
        return;
//    filePath = "E:/work/ImageManageSys/utf8/0000_051623_162252_05_004_00001_00008_00.txt";
    EncodingFormat code = FileCharacterEncoding(filePath);
    qDebug() << "code=" << (int)code;
	//读取ANSI编码格式文件
    if(code == EncodingFormat::ANSI)
        QString txtFile = filePath.left(filePath.size() -3);
        txtFile += "txt";
        QFile file(filePath);
        if(file.open(QIODevice::ReadOnly)) {
    //        qDebug() << file.errorString();
            QTextCodec::setCodecForLocale(QTextCodec::codecForName("gb2312"));//中文转码声明
            QString temStr;
            while(!file.atEnd())
                    QByteArray arr = file.readAll();
                    arr.replace(0x0B,0x0D);
                    temStr = QString::fromLocal8Bit(arr, arr.length());//Window下的QByteArray转QString
                    m_paraText->append(temStr);
            //读取任务号
            while (!file.atEnd())
               QString line = file.readLine();
               if(line.contains(u8"任务代号:", Qt::CaseSensitive))
                    int pos = line.lastIndexOf(":");
                    QString taskNum = line.right(line.size() - pos - 2);
                    taskNum = taskNum.trimmed();
                    m_taskNumSet.insert(taskNum);
                    break;
           file.close();
    //读取UTF-8编码格式文件
    if(code == EncodingFormat::UTF8)
       //读取utf8编码格式
       m_paraText->clear();
           if (!m_paraText) {
               qDebug() << "m_paraText is null!";
               return;
           QString txtFile = filePath.left(filePath.size() -3);
           txtFile += "txt";
           QFile file(filePath);
           if(!file.open(QIODevice::ReadOnly)) {
               qDebug() << file.errorString();
           QTextStream in(&file);
           in.setCodec("UTF-8");  // 设置编码为UTF-8
           QString chineseText;
           while(!in.atEnd()) {
               QString line = in.readLine();
               if(line.contains(u8"任务代号:", Qt::CaseSensitive))
                   int pos = line.lastIndexOf(":");
                   QString taskNum = line.right(line.size() - pos - 2);
                   taskNum = taskNum.trimmed();
                   m_taskNumSet.insert(taskNum);
       //            break;
               m_paraText->append(line); // 添加到QTextEdit控件中
           file.close();
}

三、参考

hellokandy