QT 自动识别文本文件的编码格式

server/2024/10/9 11:18:03/

这是我记录Qt学习过程心得文章的第一篇,也是前一段时间遇到的一个实实在在的问题,就是读取文本文件经常出现乱码,围绕读取文本文件时预先检测文本文件的编码格式,然后再在读取的时候自动设置对应的编码,我问遍度娘,遍寻CSDN,甚至请教了各路AI大神,终于解决了这个问题,可以通过检测文件头标志判断UTF-8、UTF-16LE/BE、GBK等格式,确保文本数据的使用QTextStream正确读取。

示例代码:

//获取文件编码格式函数
QTextCodec *Skysonya::getFileCharacterEncoding(const QString &fileName)
{//假定默认编码utf8EncodingFormat encoding = EncodingFormat::UTF8;QString codecName = "UTF-8";  //为了qDebug显示用QFile file(fileName);if (file.open(QIODevice::ReadOnly)){QByteArray firstBytes = file.read(3);qDebug() << "FirstBytes:" << firstBytes << Qt::endl;if (firstBytes.startsWith("\xEF\xBB\xBF")){// UTF-8 with BOMencoding = EncodingFormat::UTF8BOM;codecName = "UTF-8-BOM";}else if (firstBytes.startsWith("\xFF\xFE")){// UTF-16LEencoding = EncodingFormat::UTF16LE;codecName = "UTF-16LE";}else if (firstBytes.startsWith("\xFE\xFF")){// UTF-16BEencoding = EncodingFormat::UTF16BE;codecName = "UTF-16BE";}else{// ANSI or UTF-8QFile afile(fileName);afile.open(QIODevice::ReadOnly);QTextCodec::ConverterState converterState;QTextCodec *textcodec =QTextCodec::codecForName("utf-8");  //尝试用utf8转换,如果无效字符数大于0,则表示是ansi编码int num{};while (!afile.atEnd()){QByteArray line = afile.readLine();  //读取一行ASCII码qDebug() << "Line:" << line << Qt::endl;textcodec->toUnicode(line.constData(), line.size(), &converterState);num += converterState.invalidChars;if (num > 0) break;}encoding = (num > 0) ? EncodingFormat::ANSI : EncodingFormat::UTF8;codecName = (num > 0) ? "GB18030" : "UTF-8";}qDebug() << "FileEncoding:" << encoding << codecName << Qt::endl;file.close();}QTextCodec *textCodec;switch (encoding){case EncodingFormat::ANSI:textCodec = QTextCodec::codecForName("GB18030");codecName = "GB18030";break;case EncodingFormat::UTF16LE:textCodec = QTextCodec::codecForName("UTF-16LE");codecName = "UTF-16LE";break;case EncodingFormat::UTF16BE:textCodec = QTextCodec::codecForName("UTF-16BE");codecName = "UTF-16BE";break;case EncodingFormat::UTF8:textCodec = QTextCodec::codecForName("UTF-8");codecName = "UTF-8";break;case EncodingFormat::UTF8BOM:textCodec = QTextCodec::codecForName("UTF-8");//QTextCodec没有UTF-8-ROM这种编码格式codecName = "UTF-8-BOM";break;default:textCodec = QTextCodec::codecForName("UTF-8");break;}qDebug() << "TextCodec:" << textCodec << codecName << Qt::endl;return textCodec;
}

具体使用

//用QTextStream读取文件,整体读取
QString Skysonya::openFileByStreamWhole(const QString &fileName)
{QFile file(fileName);if (!file.exists()){messageBox("Warning", tr("打开"), "文件不存在: " + file.errorString());return NULL;}if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){messageBox("Warning", tr("打开"), "打开文件失败: " + file.errorString());return NULL;}QTextStream textStream(&file);  //用文本流读取文件内容// textStream.setAutoDetectUnicode(true);  //自动检测UnicodetextStream.setCodec(getFileCharacterEncoding(fileName));QString text = textStream.readAll();  //读取全部内容file.close();return text;
}
//打开
void MainWindow::slot_open_triggered()
{QAction *action = qobject_cast<QAction *>(sender());QString dlgTitle = "打开";           //对话框标题QString filter = "所有文件(*.txt)";  //文件过滤器QString currentFile = QFileDialog::getOpenFileName(this, dlgTitle, "", filter);QFileInfo fileinfo = QFileInfo(currentFile);setWindowTitle(wTitle + " - " + fileinfo.fileName());ui->plainMainEdit->setPlainText(skysonya.openFileByStreamWhole(currentFile));
}

我时写了一个类,类的头文件如下:

#ifndef SKYSONYA_H
#define SKYSONYA_H
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QObject>
#include <QPushButton>
#include <QString>
#include <QTextCodec>enum EncodingFormat
{ANSI,UTF16LE,UTF16BE,UTF8,UTF8BOM,
};class Skysonya : public QObject
{Q_OBJECTQ_ENUM(EncodingFormat)
public:explicit Skysonya(QObject *parent = nullptr);~Skysonya();QString doAppAbout(QString appName);                                  //程序关于信息bool messageBox(QString msgType, QString dlgTitle, QString strInfo);  //中文提示对话框QTextCodec *getFileCharacterEncoding(const QString &fileName);        //获取文件编码格式函数QString openFileByIOWhole(const QString &fileName);                   //用QFile打开文件,整体读取QString openFileByIOLines(const QString &fileName);                   //用QFile打开文件,逐行读取QString openFileByStreamWhole(const QString &fileName);               //用QTextStream读取文件,整体读取QString openFileByStreamLines(const QString &fileName);               //用QTextStream读取文件,逐行读取bool saveFileByIOWhole(const QString &fileName, QString text);        //用QFile保存文件,整体保存bool saveFileByStreamWhole(const QString &fileName, QString text);    //用QTextStream保存文件,整体保存private:QString appVersion;       //软件版本号QString buildTime;        //程序构建时间QString qtVersion;        // QT版本号QString fun_buildTime();  //获取程序构建时间
};#endif  // SKYSONYA_H

完整的示例地址:https://download.csdn.net/download/skysonya_shisy/89861254


http://www.ppmy.cn/server/129238.html

相关文章

线性代数入门指南

在数学的广袤领域中&#xff0c;线性代数犹如一座神秘而又充满魅力的殿堂&#xff0c;等待着初学者去探索。当你踏入线性代数的大门&#xff0c;便开启了一段充满挑战与惊喜的知识之旅。 线性代数是什么呢&#xff1f;简单来说&#xff0c;它是一门研究线性方程组、向量空间、线…

【权威出版|稳定检索】2024年信息学、网络与计算机应用技术国际会议(INCAT 2024)

2024 International Conference on Informatics, Networking, and Computer Application Technology 【1】大会信息 会议名称&#xff1a;2024年信息学、网络与计算机应用技术国际会议 会议简称&#xff1a;INCAT 2024 大会时间&#xff1a;请查看官网 大会地点&#xff1a;中…

【3D目标检测】激光雷达和相机联合标定(一)——ROS同步解包

ROS同步解包 引言1 鱼香ROS一键安装ros-docker脚本&#xff1a;2 指定目录映射3 数据解包3.1 解包脚本3.2 依赖安装3.3 运行脚本&#xff0c;解包 引言 总结步骤如下&#xff1a; 采集同步数据&#xff1a;ROS录制&#xff08;推荐&#xff09;&#xff0c;或者代码同步触发采…

一分钟掌握 Java18 新特性

1. 简单的 Vector API (JEP 419) 描述&#xff1a; Java 18 引入了 Vector API 的第二个版本&#xff0c;旨在提供对向量计算的支持&#xff0c;使得开发者可以利用硬件的 SIMD&#xff08;单指令多数据&#xff09;特性来提高性能。 代码示例&#xff1a; import jdk.incuba…

优先级队列

1. 优先级队列 1. 1 前言 队列是一种基于先进先出(FIFO)的数据结构&#xff0c;但是在某些情况下&#xff0c;我们操作的数据可能带有优先级&#xff0c;这时候通常要求我们将优先级高的元素先出队列&#xff0c;在这种情况下使用普通的队列就不能满足我们的需求&#xff0c;因…

MySQL中的InnoDB存储引擎

MySQL 中的 InnoDB 存储引擎是一个广泛使用的存储引擎&#xff0c;其支持事务、行级锁、外键约束以及多版本并发控制&#xff08;MVCC&#xff09;。下面详细介绍 InnoDB 的各个方面&#xff1a; 1. InnoDB 存储引擎 特点&#xff1a;InnoDB 是 MySQL 的默认存储引擎&#xff…

git pull

# git reset --hard # git clean -f #git pull git pull origin master

ClickHouse之更新表(ReplicatedReplacingMergeTree)

CK没有更新的方法&#xff0c;但是有一种引擎可以支持去重&#xff0c;它就是ReplicatedReplacingMergeTree&#xff1b; 一种是手工执行optimize table&#xff1b; 另一种是table后面加final关键字&#xff1b; 如何设置去重&#xff1f; 需要指定order key&#xff1b;注…