本章介绍在Qt中如何实现文本文件、二进制文件的读写,以及文件和目录的管理功能。
文本文件就是以纯文本格式存储的文件,Qt提供了以下两种方式对文本文件进行读写:
继承关系:QObject <— QIODevice <— AFileDevice <— QFile
//读入文件例子
bool MainWindow::openTextByIoDevice(const QString &aFileName)
{
//由文本文件的路径构造一个QFile对象
QFile aFile(aFileName);
//判断该文件是否存在
if(!aFile.exists())
{
return false;
}
//以只读模式和文本模式打开文件,这个函数和下面的readAll()函数都是继承自QIODevice的
if(!aFile.open(QIODevice::ReadOnly|QIODevice::Text))
{
return false;
}
//给文本框组件设置文本
ui->textEditDevice->setPlainText(aFile.readAll());
//关闭文件
aFile.close();
return true;
}
//写入文件例子
bool MainWindow::saveTextByIODevice(const QString &aFileName)
{
//构造QFile对象
QFile aFile(aFileName);
//以只写模式和文本模式打开该文件
if(!aFile.open(QIODevice::WriteOnly|QIODevice::Text))
{
return false;
}
QString str=ui->textEditDevice->toPlainText();
QByteArray strBytes=str.toUtf8();
//write函数有三个重载,其中一个的形参与QByteArray有关,另外两个的形参与const char*类型有关,
//而const char*又需要经QByteArray转换,所以这里直接使用QByteArray
aFile.write(strBytes, strBytes.length());
//关闭文件
aFile.close();
return true;
}
QTextStream can operate on a QIODevice, a QByteArray or a QString. Using QTextStream’s streaming operators, you can conveniently read and write words, lines and numbers. For generating text, QTextStream supports formatting options for field padding and alignment, and formatting of numbers.
//读入文件例子
bool MainWindow::openTextByStream(const QString &aFileName)
{
//由文本文件的路径构造一个QFile对象
QFile aFile(aFileName);
//判断该文件是否存在
if(!aFile.exists())
{
return false;
}
//以只读模式和文本模式打开文件,这个函数和下面的readAll()函数都是继承自QIODevice的
if(!aFile.open(QIODevice::ReadOnly|QIODevice::Text))
{
return false;
}
//构造QTextStream对象,其构造函数有5个重载,两个与QByteArray有关,一个与QString*有关,
//一个与QFile*有关,一个与QIODevice*有关
QTextStream aStream(&aFile);
//自动检测Unicode,以使汉字正常显示
aStream.setAutoDetectUnicode(true);
//给文本框组件设置文本,这里使用了readAll函数,除此之外,还可以使用readLine逐行读取
ui->textEditDevice->setPlainText(aStream.readAll());
//关闭文件
aFile.close();
return true;
}
//写入文件例子
bool MainWindow::saveTextByStream(const QString &aFileName)
{
//构造QFile对象
QFile aFile(aFileName);
//以只写模式和文本模式打开该文件
if(!aFile.open(QIODevice::WriteOnly|QIODevice::Text))
{
return false;
}
QTextStream aStream(&aFile);
aStream.setAutoDetectUnicode(true);
QString str=ui->textEditDevice->toPlainText();
//写入文本流,<<就是流插入运算符
aStream<<str;
//关闭文件
aFile.close();
return true;
}
Qt uses Unicode to store, draw and manipulate strings. In many situations you may wish to deal with data that uses a different encoding. For example, most Japanese documents are still stored in Shift-JIS or ISO 2022-JP, while Russian users often have their documents in KOI8-R or Windows-1251. Qt provides a set of QTextCodec classes to help with converting non-Unicode formats to and from Unicode. You can also create your own codec classes.
可以使用以下代码进行全局编码设置。
QTextCodec *codec=QTextCode::codeForName("UTF-8");
QTextCodec::setCodeForLocale(codec);
除了文本文件之外,其他需要按照一定格式定义的读写文件都归为二进制文件。每种二进制文件都有自己的格式定义,写入数据时需要按照一定的顺序写入,读出时也需要按照一定的顺序读出。
Qt使用QFile和QDataStream进行二进制文件的读写。其中QFile负则文件的IO设备接口,即与文件物理交互;QDataStream以数据流的形式读取或写入文件内容。
QDataStream可以保存为两种文件:
A data stream is a binary stream of encoded information which is 100% independent of the host computer’s operating system, CPU or byte order. For example, a data stream that is written by a PC under Windows can be read by a Sun SPARC running Solaris. You can also use a data stream to read/write raw unencoded binary data. If you want a “parsing” input stream, see QTextStream. The QDataStream class implements the serialization of C++’s basic data types, like char, short, int, char *, etc. Serialization of more complex data is accomplished by breaking up the data into primitive units.(即可序列化的数据类型,如QBrush、QColor、QIcon、QImage等都属于此类。)
//示例1,写stm文件
bool MainWindow::saveDataAsStream(QString& aFileName)
{
QFile aFile(aFileName);
if(!aFile.open(QIODevice::WriteOnly|QIODevice::Truncate))
return false;
QDataStream aStream(&aFile);
//版本号,读取文件的版本号必须不低于写入文件时文件的版本号
aStream.setVersion(QDataStream::Qt_5_14);
//行列数
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;
}
for(int i=0;i<rowCount;i++)
{
for(int j=0;j<colCount;j++)
{
//假设都取字符串
QStandardItem* aItem = theModel->item(i,j);
QString depth = aItem->data(Qt::DisplayRole).toString();
aStream<<depth;
}
}
aFile.close();
return true;
}
//示例2,读stm文件
bool MainWindow::openDataAsStream(QString& aFileName)
{
QFile aFile(aFileName);
if(!aFile.open(QIODevice::ReadOnly))
return false;
QDataStream aStream(&aFile);
aStream.setVersion(QDataStream::Qt_5_14);
qint16 rowCount, colCount;
//按写的顺序读文件内容,赋值给变量
aStream>>rowCount;
aStream>>colCount;
this->resetTable(rowCount);//给表格设定行数
//字段
QString str;
for(int i=0;i<colCount;i++)
{
aStream>>str;
}
//单元格数据
QString strData;
for(int i=0;i<rowCount;i++)
{
for(int j=0;j<colCount;j++)
{
aStream>>strData;
aItem = theModel->itemFromIndex(theModel->index(i,j));
aItem->setData(strData);
}
}
aFile.closed();
return true;
}
//示例3,写dat文件
bool MainWindow::saveBinaryFile(QString& aFileName)
{
QFile aFile(aFileName);
if(!aFile.open(QIODevice::WriteOnly))
return false;
QDataStream aStream(&aFile);
//Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端,Windows系统是此类
aStream.setByteOrder(QDataStream::LittleEndian);
//行列数
qint16 rowCount = theModel->rowCount();
qint16 colCount = theModel->columnCount();
aStream.writeRawData((char*)&rowCount,sizeof(qint16));
aStream.writeRawData((char*)&colCount,sizeof(qint16));
//字段,这里之所以不用writeRawData,是因为字符串的长度不固定,使用writeBytes()会先将字符串的长度作为qint32
//类型的数据写入,再写字符串数据,这样方便文件的读取
QByteArray btArray;
QStandardItem *aItem;
for(int i=0;i<colCount;i++)
{
aItem = theModel->horizontalHeaderItem(i);
QString str = aItem->text();
btArray = str.toUtf8();
aStream.writeBytes(btArray,btArray.length());
}
//单元格数据
for(int i=0;i<rawCount;i++)
{
for(int j=0;j<colCount;j++)
{
aItem=theModel->item(i,j);
btArray=aItem->data(Qt::DisplayRole).toString().toUtf8();
aStream.writeBytes(btArray,btArray.length());
}
}
aFile.close();
return true;
}
//示例4,读dat文件
bool MainWindow::readBinaryFile(QString& aFileName)
{
QFile aFile(aFileName);
if(!aFile.open(QIODevice::WriteOnly))
return false;
QDataStream aStream(&aFile);
aStream.setByteOrder(QDataStream::LittleEndian);
//行列数,readRawData原型为readRawData(char*s,int len);
//读取len个字节的数据到s指向的存储单元中
qint16 rowCount, colCount;
aStream.readRawData((char*)&rowCount,sizeof(qint16));
aStream.readRawData((char*)&colCount,sizeof(qint16));
this->resetTable(rowCount);
//字段,readBytes原型为readBytes(char*&s,unit &len);
//读取字符串长度到len中,读取字符串到s指向的变量中
char *buf;
uint strLength;
for(int i=0;i<colCount;i++)
{
aStream.readBytes(buf,strLength);
QString str = QString::fromLocal8Bit(buf,strLength);
}
//单元格数据
QStandardItem *aItem;
QString strData;
for(int i=0;i<rawCount;i++)
{
for(int j=0;j<colCount;j++)
{
aStream.readBytes(buf,strLength);
strData = QString::fromLocal8Bit(buf,strLength);
aItem = theModel->itemFromIndex(theModel->index(i,j));
aItem->setData(str,Qt::DisplayRole);
}
}
aFile.close();
return true;
}
概览:
类名 | 说明 |
---|---|
QCoreApplication | 用于提取应用程序的路径(applicationFilePath())、程序名(applicationFileName())等信息 |
QFile | 有复制文件(copy(QString& fileName, QString& newName))、删除文件(remove(QString &fileName))等功能 |
QFileInfo | 用于提取文件信息,如路径(path())、文件名(fileName())、后缀(completeSuffix())等 |
QDir | 用于提取目录或文件信息,如获取一个目录下的文件或目录列表(entryList(Filters filters=NoFilter,SortFlags sort=NoSort)),文件重命名(rename(QString& oldName,QString& newName)) |
QTemporaryDir和QTemporaryFile | 用于创建临时目录和临时文件,使用remove()方法删除临时目录及文件 |
QFileSystemWatcher | 文件和目录监听类,监听目录下文件的添加、删除等变化,监听文件修改变化 |