文章目录
QFile类及函数的使用可参考:Qt类 | QFile类详解
一、文本文件的读写
文本文件是指以纯文本格式存储的文件,例如用Qt编写的 C++ 程序的.h与.cpp文件。HTML与XML 文件也是纯文本文件,只是其读取之后需要对内容进行解析之后再显示。
Qt 提供了两种读写纯文本文件的基本方法,
- 一种是用 QFile 类的 IODevice 读写功能直接进行读写
- 另一种是利用 QFile和QTextStream 结合起来,用流的方法进行文件读写。
1.QFile读写文本文件
QFile类是直接与 IO 设备打交道,进行文件读写操作的类,使用 QFile 可以直接打开或保存文本文件。
读取文件:
通过QFileDialog对话框选择一个文件,利用该文件名实例化QFile对象,检查文件是否存在后,利用open()函数打开文件,利用readAll()函数读取所有数据。
示例:
QString curPath=QDir::currentPath();//获取系统当前目录
QString dlgTitle="打开一个文件"; //对话框标题
QString filter="程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString aFileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
if (aFileName.isEmpty())
return;
QFile aFile(aFileName);
// aFile.setFileName(aFileName);
if (!aFile.exists()) //文件不存在
return false;
if (!aFile.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
ui->textEditDevice->setPlainText(aFile.readAll());
// while (!aFile.atEnd())
// {
// QByteArray line = aFile.readLine();//自动添加 \n
// QString str=QString::fromLocal8Bit(line); //从字节数组转换为字符串
// str.truncate(str.length()-1); //去除结尾增加的空行
// ui->textEditDevice->appendPlainText(str);
// }
aFile.close();
注意事项:
-
QFile::open()
函数打开文件时需要传递QlODevice::OpenModeFlag
枚举类型的参数 ,决定文件以什么方式打开, 这些取值可以组合QlODevice::OpenModeFlag
主要取值如下:QIODevice::ReadOnly
:只读方式打开文件,用于载入文件。QIODevice::WriteOnly
: 只写方式打开文件, 用于保存文件,隐含着Truncate,即删除文件原有的内容。QIODevice::ReadWrite
:读写方式打开文件QIODevice::Append
:以添加模式打开文件,新写入文件的数据添加到文件尾部QIODevice::Truncate
: 截取方式打开文件, 文件原有的内容全部被删除QIODevice::Text
:文本方式打开文件,读取时“\n”被自动翻译为换行符,写入时字符串结束符会自动翻译为系统平台的编码,如Windows平台下是“\r\n"
-
readAll()
函数适合读取小文件或已知大小的文件,对于大文件,使用readAll()
可能会消耗大量内存,因为它会一次性读取所有数据到内存中。在处理大文件时,可能需要考虑使用分块读取。 -
readLine()
函数- 按行读取数据,每次调用返回一行。返回一个
QByteArray
。 - 适合处理文本文件或需要逐行处理数据的场景。
- 可以处理大文件,因为它一次只读取一行。
- 需要在循环中调用,直到返回空的
QByteArray
表示读取完毕。
- 按行读取数据,每次调用返回一行。返回一个
写入(保存)文件:
通过QFileDialog对话框选择一个目标文件,利用该文件名实例化QFile对象,检查文件是否存在后,利用open()函数打开该文件,使用的模式是 QIODevice::WriteOnly I QIODevice::Text
,将 QPlaintextEdit组件的文本导出为字符串 ,然后转换为 UTF8 编码的字节数组 strBytes,然后调用 QFile :write() 函数将字节数组内容写入文件。
示例:
QString curPath=QDir::currentPath();//获取系统当前目录
QString dlgTitle="另存为一个文件"; //对话框标题
QString filter="h文件(*.h);;c++文件(*.cpp);;文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString aFileName=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
if (aFileName.isEmpty())
return;
saveTextByIODevice(aFileName);
//用IODevice方式保存文本文件
QFile aFile(aFileName);
// aFile.setFileName(aFileName);
if (!aFile.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QString str=ui->textEditDevice->toPlainText();//整个内容作为字符串
QByteArray strBytes=str.toUtf8();//转换为字节数组
// QByteArray strBytes=str.toLocal8Bit();
aFile.write(strBytes,strBytes.length()); //写入文件
aFile.close();
2.QFile与QTextStream 结合读写文本文件
QTextStream与 IO 读写设备结合 ,为数据读写提供了一些方便的方法的类,QTextStream可以与 QFile、QTemporaryFile、 QBuffer、QTcpSocket、QUdpSocket等IO 设备类结合使用。
用文本流读取文件:
在创建 QTextStream 实例时传递一个 QFile 对象,这样 QFile 对象和 QTextStream 对象就结合在一起了,利用 QTextStream 可读写文件。如果文本文件里有汉字,需要设定为自动识别 Uni code码,即调用 setAutoDetectUnicode(true)
函数。
示例:
QString curPath=QDir::currentPath();//获取系统当前目录
//调用打开文件对话框打开一个文件
QString aFileName=QFileDialog::getOpenFileName(this,"打开一个文件",curPath,
"程序文件(*.h *cpp);;文本文件(*.txt);;所有文件(*.*)");
if (aFileName.isEmpty())
return; //如果未选择文件,退出
//打开文件
QFile aFile(aFileName);
if (!aFile.exists()) //文件不存在
return false;
if (!aFile.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream aStream(&aFile); //用文本流读取文件
// aStream.setAutoDetectUnicode(true); //自动检测Unicode,才能正常显示文档内的汉字
ui->textEditStream->setPlainText(aStream.readAll());
// while (!aStream.atEnd())
// {
// str=aStream.readLine();//读取文件的一行
// ui->textEditStream->appendPlainText(str); //添加到文本框显示
// }
aFile.close();//关闭文件
写入文本流(保存文件):
示例:
QString curPath=QDir::currentPath();//获取系统当前目录
QString dlgTitle="另存为一个文件"; //对话框标题
QString filter="h文件(*.h);;c++文件(*.cpp);;文本文件(*.txt);;所有文件(*.*)"; //文件过滤器
QString aFileName=QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
if (aFileName.isEmpty())
return;
//用QTextStream保存文本文件
QFile aFile(aFileName);
if (!aFile.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QTextStream aStream(&aFile); //用文本流读取文件
// aStream.setAutoDetectUnicode(true); //自动检测Unicode,才能正常显示文档内的汉字
QString str=ui->textEditStream->toPlainText(); //转换为字符串
aStream<<str; //写入文本流
// QTextDocument *doc; //文本对象
// QTextBlock textLine; //文本中的一段
// doc=ui->textEditStream->document(); //QPlainTextEdit 的内容保存在一个 QTextDocument 里
// int cnt=doc->blockCount();//QTextDocument分块保存内容,文本文件就是硬回车符是一个block,
// QString str;
// for (int i=0; i<cnt; i++) //扫描所有 blobk
// {
// textLine=doc->findBlockByNumber(i);//用blobk编号获取block,就是获取一行
// str=textLine.text(); //转换为文本,末尾无\n
// aStream<<str<<"\n";
// }
aFile.close();//关闭文件
3.解决中文乱码问题
在使用 QTextStream 读写有中文内容的文本文件时,为了能正确识别 Unicode 码, 需要调用setAutoDetectUnicode(true)
,设置 QTextStream 可以自动识别 Unicode 码。 如果不做此设置,读取文件的中文将是乱码,无法正常显示。
为解决 Unicode 的识别问题,可以在应用程序中做全局的设置 ,使得应用程序支持 Unicode。方法是在main()函数中使用QTextCodec类进行编码设置。例如:
#include <QTextCodec>
int main(int argc, char *argv[])
{
//解决汉字乱码问题
QTextCodec *codec = QTextCodec::codecForName("UTF-8"); //查找编解码器对象
QTextCodec::setCodecForLocale(codec); //为当前区域设置指定的编解码器
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
-
QTextCodec
是Qt框架中用于文本编解码的类。 -
codecForName
函数–用于查找和返回与给定名称最匹配的编解码器对象[static] QTextCodec *QTextCodec::codecForName(const QByteArray &name) [static] QTextCodec *QTextCodec::codecForName(const char *name)
-
函数说明:
用于查找和返回与给定名称最匹配的编解码器对象。匹配过程不区分大小写,意味着"UTF-8"、"utf-8"和"UTF-8"都会被认为是相同的。如果没有找到匹配的编解码器,函数将返回
nullptr
-
示例:
#include <QTextCodec> int main() { // 获取UTF-8编解码器 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); if (codec) { // 使用编解码器进行编码转换 QByteArray utf8Data = codec->fromUnicode("你好,世界!"); qDebug() << "UTF-8 encoded data:" << utf8Data; } else { qDebug() << "Codec not found for UTF-8"; } return 0; }
-
-
setCodecForLocale
函数–为当前区域设置指定的编解码器[static] void QTextCodec::setCodecForLocale(QTextCodec *c)
-
函数说明:
用于为当前区域设置指定的编解码器,如果传递给函数的参数
c
是nullptr
,则会将编解码器重置为系统默认的编解码器。
-
二、二进制文件读写
除了文本文件之外,其他需要按照一定的格式定义读写的文件都称为二进制文件。每种格式的二进制文件都有自己的格式定义,写入数据时按照一定的顺序写入,读出时也按照相应的顺序读出。例如,地球物理中常用的 SEG-Y 格式文件,必须按照其标准格式要求写入数据才符合这种文件的格式规范,该取数据时也需要按照格式定义来读出。
Qt使用 QFile 和 QDataStream 进行二进制数据文件的读写。 QFile 负责文件的 IO 设备接口,即与文件的物理交互, QDataStream 以数据流的方式读取文件内容或写入文件内容。
根据 QDataStrearm 保存文件时使用的数据编码的方式不同,可以保存为两种文件。
-
用 Qt 预定义编码保存各种类型数据的文件,定义文件后缀为 “.stm”。Qt 预定义编码是指在写入某个类型数据,如整形数、字符串等到文件流时,使用 Qt 预定义的编码。
QDataStrearm 以流操作写入这些数据时,并不知道文件里每个字节是如何存储的,但是知道数据写入的顺序,以及每次写入数据的类型,在文件数据读出时,只需要按照顺序和类型对应读出即可。
-
标准编码数据文件,定义文件后缀为 “.dat”。在将数据写到文件时,完全使用数据的二进制原始内容,每个字节都有具体的定义,在读出数据时,只需要根据每个字节的定义写出数据即可。
两种文件的要点:
读写 stm 文件,
这种方法使用简单,但是文件的格式不完全透明,不能创建用于交换的通用格式文件
读写 dat 文件,
这种方法创建通用格式文件,即文件格式完全透明
以标准编码方式创建文件,使文件的每个字节都有具体的定义。用户在读取这种文件时,按照文件格式定义读取出每个字节数据并做解析即可,不管使用什么编程语言都可以编写读写文件的程序
使用 QDataStream 的流操作方式读写文件的特点:
- 读写操作都比较方便,支持读写各种数据类型,包括 Qt 的一些类,还可以为流数据读写扩展自定义的数据类型。读写某种类型的数据时,只要是流支持即可,而在文件内部是如何存储的,用户无需关心,由 Qt 预定义。
- 写文件和读文件时必须保证使用的流版本兼容,即流的版本号相同,或读取文件的流版本号高于写文件时的流版本号。这是因为在不同的流版本中,流支持的数据类型的读写方式可能有所改变, 必须保证读写版本的兼容
- 用这种方式保存文件时,写入数据采用 Qt 预定义的编码,即写入文件的二进制编码是由 Qt 预定义的,写多少个字节、字节是什么样的顺序,用户是不知道的。如果是由 QDataStream 读取数据, 只需按类型读出即可。若用其他编程语言来读取文件内容,就会存在问题。
1.Qt预定义编码文件的读写
1.1 保存(写入)stm文件
保存为一个stm文件的过程:
-
首先,通过文本对话框选择一个保存(写入)文件
void MainWindow::on_actSave_triggered() { //以Qt预定义编码保存数据文件 QString curPath=QDir::currentPath(); QString aFileName=QFileDialog::getSaveFileName(this,tr("选择保存文件"),curPath, "Qt预定义编码数据文件(*.stm)"); if (aFileName.isEmpty()) return; // if (saveDataAsStream(aFileName)) //保存为流数据文件 QMessageBox::information(this,"提示消息","文件已经成功保存!"); }
-
然后,创建 QFile 对象 aFile 打开文件,
-
创建 QDataStream 对象 Stream 与 QFile 对象关联。
-
在开始写数据流之前,为 QDataStream 对象 aStream 设置版本号,即调用setVersion()函数
注意:以 Qt 的预定义类型编码保存的文件需要指定流版本号,因为每个版本的 Qt 对数据类型的编码可能有差别,需要保证写文件和读文件的流版本是兼容的
-
接下来,按照需要保存数据的顺序写入文件流。
- 在文件开始,先写入行数和列数,因为行数与列数关系到后面的数据是如何组织的
- 接着,读取各列的表头并写入数据流
- 然后逐行扫描表格的数据类型,将每一行的列数据写入数据流。数据流写入数据时都使用运算符“<<"。
bool MainWindow::saveDataAsStream(QString &aFileName) {//将模型数据保存为Qt预定义编码的数据文件 QFile aFile(aFileName); //以文件方式读出 if (!(aFile.open(QIODevice::WriteOnly | QIODevice::Truncate))) return false; QDataStream aStream(&aFile); aStream.setVersion(QDataStream::Qt_5_15); //设置版本号,写入和读取的版本号要兼容 qint16 rowCount=theModel->rowCount(); //数据模型行数 qint16 colCount=theModel->columnCount(); //数据模型列数 aStream<<rowCount; //写入文件流,行数 aStream<<colCount;//写入文件流,列数 //获取表头文字 for (int i=0;i<theModel->columnCount();i++) { QString str=theModel->horizontalHeaderItem(i)->text();//获取表头文字 aStream<<str; //字符串写入文件流,Qt预定义编码方式 } //获取数据区的数据 for (int i=0;i<theModel->rowCount();i++) { QStandardItem* aItem=theModel->item(i,0); //测深 qint16 ceShen=aItem->data(Qt::DisplayRole).toInt(); aStream<<ceShen;// 写入文件流,qint16 aItem=theModel->item(i,1); //垂深 qreal chuiShen=aItem->data(Qt::DisplayRole).toFloat(); aStream<<chuiShen;//写入文件流, qreal aItem=theModel->item(i,2); //方位 qreal fangWei=aItem->data(Qt::DisplayRole).toFloat(); aStream<<fangWei;//写入文件流, qreal aItem=theModel->item(i,3); //位移 qreal weiYi=aItem->data(Qt::DisplayRole).toFloat(); aStream<<weiYi;//写入文件流, qreal aItem=theModel->item(i,4); //固井质量 QString zhiLiang=aItem->data(Qt::DisplayRole).toString(); aStream<<zhiLiang;// 写入文件流,字符串 aItem=theModel->item(i,5); //测井 bool quYang=(aItem->checkState()==Qt::Checked); aStream<<quYang;// 写入文件流,bool型 } aFile.close(); return true; }
根据 saveDataAsStream() 函数的代码,可知 Qt 预定义编码保存的 stm 文件的格式,如下:
1.2 读取 stm 文件
读取 stm 文件的过程:
-
首先,通过文本对话框选择一个待读取的 stm 文件
void MainWindow::on_actOpen_triggered() { QString curPath=QDir::currentPath(); //调用打开文件对话框打开一个文件 QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath, "Qt预定义编码数据文件(*.stm)"); if (aFileName.isEmpty()) return; // if (openDataAsStream(aFileName)) //读取流数据文件 QMessageBox::information(this,"提示消息","文件已经打开!"); }
-
然后,创建 QFile 对象 aFile 打开文件,
-
创建 QDataStream 对象 Stream 与 QFile 对象关联。
-
在开始读取数据流之前,为 QDataStream 对象 aStream 设置流版本号,即调用setVersion()函数,应该等于或高于数据保存时的流版本号
注意:以 Qt 的预定义类型编码保存的文件需要指定流版本号,因为每个版本的 Qt 对数据类型的编码可能有差别,需要保证写文件和读文件的流版本是兼容的
-
接下来,按照需要写入数据的顺序和类型,相应地读出每个数据
- 文件里最早的两个数据是表格的行数和列数, 读出这两个数据,就能知道数据的行数和列数,并调用自定义函数resetTable()函数给数据模型复位,并设置其行数。
- 然后,将保存的每行数据读入到数据模型的每个项中,这样窗口上的 QTableView 组件就可以显示数据了
bool MainWindow::openDataAsStream(QString &aFileName) { //从Qt预定义流文件读入数据 QFile aFile(aFileName); //以文件方式读出 if (!(aFile.open(QIODevice::ReadOnly))) return false; QDataStream aStream(&aFile); //用文本流读取文件 aStream.setVersion(QDataStream::Qt_5_9); //设置流文件版本号 qint16 rowCount,colCount; aStream>>rowCount; //读取行数 aStream>>colCount; //列数 this->resetTable(rowCount); //表格复位 //获取表头文字 QString str; for (int i=0;i<colCount;i++) aStream>>str; //读取表头字符串 //获取数据区文字, qint16 ceShen; qreal chuiShen; qreal fangWei; qreal weiYi; QString zhiLiang; bool quYang; QStandardItem *aItem; QModelIndex index; for (int i=0;i<rowCount;i++) { aStream>>ceShen;//读取测深, qint16 index=theModel->index(i,0); aItem=theModel->itemFromIndex(index); aItem->setData(ceShen,Qt::DisplayRole); aStream>>chuiShen;//垂深,qreal index=theModel->index(i,1); aItem=theModel->itemFromIndex(index); aItem->setData(chuiShen,Qt::DisplayRole); aStream>>fangWei;//方位,qreal index=theModel->index(i,2); aItem=theModel->itemFromIndex(index); aItem->setData(fangWei,Qt::DisplayRole); aStream>>weiYi;//位移,qreal index=theModel->index(i,3); aItem=theModel->itemFromIndex(index); aItem->setData(weiYi,Qt::DisplayRole); aStream>>zhiLiang;//固井质量,QString index=theModel->index(i,4); aItem=theModel->itemFromIndex(index); aItem->setData(zhiLiang,Qt::DisplayRole); aStream>>quYang;//bool index=theModel->index(i,5); aItem=theModel->itemFromIndex(index); if (quYang) aItem->setCheckState(Qt::Checked); else aItem->setCheckState(Qt::Unchecked); } aFile.close(); return true; }
2.标准编码文件的读写
2.1 保存为dat文件
保存为 dat 文件的过程:
-
首先,通过文本对话框选择保存(写入)文件
void MainWindow::on_actSaveBin_triggered() {//保存二进制文件 QString curPath=QDir::currentPath(); //调用打开文件对话框选择一个文件 QString aFileName=QFileDialog::getSaveFileName(this,tr("选择保存文件"),curPath, "二进制数据文件(*.dat)"); if (aFileName.isEmpty()) return; // if (saveBinaryFile(aFileName)) //保存为流数据文件 QMessageBox::information(this,"提示消息","文件已经成功保存!"); }
-
然后,创建 QFile 对象 aFile 打开文件,
-
创建 QDataStream 对象 Stream 与 QFile 对象关联。
-
在保存为标准编码的二进制文件时,无须指定 QDataStream 版本,但是,如有必要,需要为文件指定字节顺序,字节顺序分为大端字节序和小端字节序
-
使用 QdataStrearm 的 writeRawData() 和 writeBytes() 函数将数据写入到数据流中
int QDataStream::writeRawData(const char *s, int len) QDataStream &QDataStream::writeBytes(const char *s, uint len)
-
writeRawData函数
将 qint8、qintl6、qreal 等类型的数据保存到文件中
-
writeBytes函数
- 写入操作首先写入一个
quint32
类型的值,表示随后要写入的字节数。 - 然后,从缓冲区
s
开始,写入len
个字节的数据。
- 写入操作首先写入一个
bool MainWindow::saveBinaryFile(QString &aFileName) { //保存为纯二进制文件 QFile aFile(aFileName); //以文件方式读出 if (!(aFile.open(QIODevice::WriteOnly))) return false; QDataStream aStream(&aFile); //用文本流读取文件 // aStream.setVersion(QDataStream::Qt_5_9); //无需设置数据流的版本 aStream.setByteOrder(QDataStream::LittleEndian);//windows平台 // aStream.setByteOrder(QDataStream::BigEndian);//QDataStream::LittleEndian qint16 rowCount=theModel->rowCount(); qint16 colCount=theModel->columnCount(); aStream.writeRawData((char *)&rowCount,sizeof(qint16)); //写入文件流 aStream.writeRawData((char *)&colCount,sizeof(qint16));//写入文件流 //获取表头文字 QByteArray btArray; QStandardItem *aItem; for (int i=0;i<theModel->columnCount();i++) { aItem=theModel->horizontalHeaderItem(i); //获取表头item QString str=aItem->text(); //获取表头文字 btArray=str.toUtf8(); //转换为字符数组 aStream.writeBytes(btArray,btArray.length()); //写入文件流,长度uint型,然后是字符串内容 } //获取数据区文字, qint8 yes=1,no=0; //分别代表逻辑值 true和false for (int i=0;i<theModel->rowCount();i++) { aItem=theModel->item(i,0); //测深 qint16 ceShen=aItem->data(Qt::DisplayRole).toInt();//qint16类型 aStream.writeRawData((char *)&ceShen,sizeof(qint16));//写入文件流 aItem=theModel->item(i,1); //垂深 qreal chuiShen=aItem->data(Qt::DisplayRole).toFloat();//qreal 类型 aStream.writeRawData((char *)&chuiShen,sizeof(qreal));//写入文件流 aItem=theModel->item(i,2); //方位 qreal fangWei=aItem->data(Qt::DisplayRole).toFloat(); aStream.writeRawData((char *)&fangWei,sizeof(qreal)); aItem=theModel->item(i,3); //位移 qreal weiYi=aItem->data(Qt::DisplayRole).toFloat(); aStream.writeRawData((char *)&weiYi,sizeof(qreal)); aItem=theModel->item(i,4); //固井质量 QString zhiLiang=aItem->data(Qt::DisplayRole).toString(); btArray=zhiLiang.toUtf8(); aStream.writeBytes(btArray,btArray.length()); //写入长度,uint,然后是字符串 // aStream.writeRawData(btArray,btArray.length());//对于字符串,应使用writeBytes()函数 aItem=theModel->item(i,5); //测井取样 bool quYang=(aItem->checkState()==Qt::Checked); //true or false if (quYang) aStream.writeRawData((char *)&yes,sizeof(qint8)); else aStream.writeRawData((char *)&no,sizeof(qint8)); } aFile.close(); return true; }
-
dat文件格式:
2.2 读取 dat 文件
读取 dat 文件的过程:
-
首先,通过文本对话框选择一个待读取的 dat 文件
void MainWindow::on_actOpenBin_triggered() {//打开二进制文件 QString curPath=QDir::currentPath();//系统当前目录 QString aFileName=QFileDialog::getOpenFileName(this,tr("打开一个文件"),curPath, "二进制数据文件(*.dat)"); if (aFileName.isEmpty()) return; // if (openBinaryFile(aFileName)) //读取流数据文件 QMessageBox::information(this,"提示消息","文件已经打开!"); }
-
然后,创建 QFile 对象 aFile 打开文件,
-
创建 QDataStream 对象 Stream 与 QFile 对象关联。
-
使用 setByteOrder() 为文件指定字节顺序,保证与写入文件时用的字节序一致
-
使用 QdataStrearm 的 readRawData() 和 readBytes() 函数从数据流中读取数据
int QDataStream::readRawData(char *s, int len) QDataStream &QDataStream::readBytes(char *&s, uint &l)
-
读入到数据模型的每个项中,这样窗口上的 QTableView 组件就可以显示数据了
bool MainWindow::openBinaryFile(QString &aFileName) {//打开二进制文件 QFile aFile(aFileName); //以文件方式读出 if (!(aFile.open(QIODevice::ReadOnly))) return false; QDataStream aStream(&aFile); //用文本流读取文件 // aStream.setVersion(QDataStream::Qt_5_9); //设置数据流的版本 aStream.setByteOrder(QDataStream::LittleEndian); // aStream.setByteOrder(QDataStream::BigEndian); qint16 rowCount,colCount; aStream.readRawData((char *)&rowCount, sizeof(qint16)); aStream.readRawData((char *)&colCount, sizeof(qint16)); this->resetTable(rowCount); //获取表头文字,但是并不利用 char *buf; uint strLen; //也就是 quint32 for (int i=0;i<colCount;i++) { aStream.readBytes(buf,strLen);//同时读取字符串长度,和字符串内容 QString str=QString::fromLocal8Bit(buf,strLen); //可处理汉字 } //获取数据区数据 QStandardItem *aItem; qint16 ceShen; qreal chuiShen; qreal fangWei; qreal weiYi; QString zhiLiang; qint8 quYang; //分别代表逻辑值 true和false QModelIndex index; for (int i=0;i<rowCount;i++) { aStream.readRawData((char *)&ceShen, sizeof(qint16)); //测深 index=theModel->index(i,0); aItem=theModel->itemFromIndex(index); aItem->setData(ceShen,Qt::DisplayRole); aStream.readRawData((char *)&chuiShen, sizeof(qreal)); //垂深 index=theModel->index(i,1); aItem=theModel->itemFromIndex(index); aItem->setData(chuiShen,Qt::DisplayRole); aStream.readRawData((char *)&fangWei, sizeof(qreal)); //方位 index=theModel->index(i,2); aItem=theModel->itemFromIndex(index); aItem->setData(fangWei,Qt::DisplayRole); aStream.readRawData((char *)&weiYi, sizeof(qreal)); //位移 index=theModel->index(i,3); aItem=theModel->itemFromIndex(index); aItem->setData(weiYi,Qt::DisplayRole); aStream.readBytes(buf,strLen);//固井质量 zhiLiang=QString::fromLocal8Bit(buf,strLen); index=theModel->index(i,4); aItem=theModel->itemFromIndex(index); aItem->setData(zhiLiang,Qt::DisplayRole); aStream.readRawData((char *)&quYang, sizeof(qint8)); //测井取样 index=theModel->index(i,5); aItem=theModel->itemFromIndex(index); if (quYang==1) aItem->setCheckState(Qt::Checked); else aItem->setCheckState(Qt::Unchecked); } aFile.close(); return true; }
三、文件目录操作类
1.文件目录操作相关的类
Qt 为文件和目录操作提供了一些类 ,利用这些类可以方便 实现一些操作。 Qt 提供的与文件和目录操作相关的类包括以下几个:
- QCoreApplication:用于提取应用程序路径、程序名等文件信息
- QFile:除了打开文件操作外,QFile 还有复制文件、删除文件等功能
- QFilelnfo:用于提取文件的信息,包括路径、文件名、后缀等
- QDir:用于提取目录或文件信息,获取一个目录下的文件或目录列表,创建或删除目录和文件,文件重命名等操作
- QTemporaryDir和QTemporaryFile:用于创建临时目录和临时文件
- QFileSystemWatcher:文件和目录监听类 ,监听目录下文件的添加 、删除等变化,监听文件修改变化
2.QCoreApplication类
QCoreApplication 是为无 GUI 应用提供事件循环的类,是所有应用程序的基类,其子类 QGuiApplication 为有 GUI 界面的应用程序提供流控制和主要的设定,QGuiApplication 的子类QApplication 为基于 QWidget 的应用程序提供支持,包括界面的初始化等。创建的 Qt Widget Application 都是基于 QApplication 的,在 main() 函数里可以看到 QApplication的应用。
QCoreApplication 提供了一些有用的静态函数,可以获取应用程序的名称、启动路径等信息
3.QFile类
除了打开文件提供读写操作外,QFile还有一些静态函数和成员函数用于文件操作。
QFile的一些静态函数:
QFile的对应成员函数:
4.QFileInfo类
QFileInfo类的接口函数提供文件的各种信息。
QFileInfo常见接口函数和功能:
除了exists()是静态函数之外,其他都是公共接口函数。QFilelnfo 提供的这些函数可以提取文件的信息,包括目录名、文件基名(不带后缀) 、文件后缀等,利用这些函数可以实现灵活的文件操作。
5.QDir类
QDir 是进行目录操作的类,在创建 QDir 时传递一个目录字符串作为当前目录,然后 QDir 函数就可以针对当前目录或目录下的文件进行操作 。
QDir的一些静态函数:
QDir的一些公共接口函数:
QDir::Filter 枚举类型的常用取值:
-
QDir::AllDirs
:列出所有目录名 -
QDir::Files
:列出所有文件 -
QDir::Drives
:列出所有盘符 -
QDir::NoDotAndDotDot
:不列出特殊的符号,如“.“和”…" -
QDir::AllEntries
:列出目录下所有项目
6.QTemporaryDir和QTemporaryFile类
QTemporaryDir 和 QTemporaryFile 是用于创建、删除临时目录的类,主要函数如下:
在系统临时目录 ,即 QDir::tempPath 目录下创建一个临时目录, 临时目录名称以QCoreApplication::applicationName() 为前缀,后加6个字符。临时目录可以设置为使用完后自动删除,即临时目录变量删除时,临时目录也删除。
QTemporayFile 是用于创建临时文件的类 ,临时文件保存在系统临时目录下。临时文件以QCoreApplication::applicationName() 作为文件名, 以“XXXXXX” 6个随机数字作为文件后缀。将QTemporaryFile: :setAutoRemove() 函数设置为是否自动删除临时文件,QTemporaryFile::open() 函数用于打开临时文件,只有打开临时文件,才实际创建了此文件。
7.QFileSystemWatcher类
QFileSystemWatcher 是对目录和文件进行监听的类。把某些目录或文件添加到 QFileSystemWatcher 对象的监听列表后,当目录下发生文件新建、删除等操作时会发射 directorChanged() 信号,当监听的文件发生修改、重命名等操作时, 会发射 fileChanged() 信号。所以,这个类在进行目录或文件监听时起作用。
QFileSystemWatcher的主要接口: