系列文章目录
文章目录
-
系列文章目录
-
前言
-
一、判断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