Qt之文件系统
一、文本文件的读写
1.QFile读取文本文件
QFile类是直接与IO设备打交道,进行文件读写操作的类,使用QFile可以直接打开或保存文本文件。
示例代码:
void MainWindow::on_btn_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "打开一文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFile file(fileName);
if (!file.exists()) {
qDebug() << "文件不存在";
return;
}
if (!file.open(QIODevice::ReadOnly |QIODevice::Text)) {
qDebug() << "文件打开失败";
return;
}
m_pTextEdit->setPlainText(file.readAll());
file.close();
}
定义QFile对象变量fileName时将文件名传递给它,检查文件存在后,通过open()函数打开文件。
QFile::open()函数打开文件时需要传递QIODevice::OpenModeFlag枚举类型的参数,决定文件以什么方式打开,QIODevice::OpenModeFlag类型的主要取值如下:
- QIODevice::ReadOnly:以只读方式打开文件,用于载入文件。
- QIODevice::WriteOnly:以只写方式打开文,用于保存文件。
- QIODevice::ReadWrite:以读写方式打开。
- QIODevice::Append:以添加模式打开,新写入文件的数据添加到文件尾部。
- QIODevice::Truncate:以截取方式打开文件,文件原有的内容全部被删除。
- QIODevice::Text:以文本方式打开文件,读取时"\n"被自动翻译为换行符,写入时字符串结束符会自动翻译为系统平台的编码,如Windows平台下是“\r\n”。
这些取值可以组合,例如QIODevice::ReadOnly | QIODevice::Text表示只读和文本方式打开文件;文本内容读取结束后,需要调用QFile::close()函数关闭文件。
2.QFile写入文本文件
void MainWindow::on_btn_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "另存为一个文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getSaveFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "文件打开失败";
return;
}
QString str = m_pTextEdit->toPlainText(); //整个内容作为字符串
QByteArray strBytes = str.toUtf8(); //转换为字节数组
qint64 ret = file.write(strBytes, strBytes.length()); //写入文件
if (ret != strBytes.length()) {
qDebug() << "文件写入失败";
}
file.close();
}
为了保存文件,用open()打开文件时,使用的模式是QIODevice::WriteOnly | QIODevice::Text。使用WriteOnly隐含着Truncate,即删除文件原有内容,并将QString类型的文本内容通过toUtf8()函数转换为UTF8编码的字节数组strBytes,然后调用QFile::write()函数将字节数组内容写入文件。
二、QFile和QTextSTream结合读写文本文件
1.QTextSTream读取文件
QTextStream与IO读写设备结合,为数据读写提供了一些方便的方法的类,QTextStream可以与QFile、QTemporaryFile、QBuffer、QTcpSocket和QUdpSocket等IO设备类结合使用。
下面的示例将QFile和QTextStream结合,读取文本文件:
void MainWindow::on_btn_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "打开一文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFile file(fileName);
if (!file.exists()) {
qDebug() << "文件不存在";
return;
}
if (!file.open(QIODevice::ReadOnly |QIODevice::Text)) {
qDebug() << "文件打开失败";
return;
}
QTextStream stream(&file); //用文本流读取文件
stream.setAutoDetectUnicode(true); //自动检测Unicode,才能显示汉字
m_pTextEdit->setPlainText(stream.readAll());
file.close();
}
在创建QTextStream实例时传递一个QFile对象,这样,QFile对象和QTextStream对象就结合在一起了,利用QTextStream可读写文件,如果文本文件里有汉字,需要设定为自动识别Unicode码,即调用setAutoDetectUnicode(true)函数。
在上述代码里,使用QTextStream::readAll()函数一次读出文件全部文本内容,但是QTextStream还提供了一些其他方便使用的接口函数,如使用QTextStream可以方便的实现逐行读取文本文件内容。对openTextByStream()函数稍作修改,使其以逐行的方式读取文件内容,这种方式适用于需要逐行解析字符串的内容的应用。
示例代码如下所示:
void MainWindow::on_btn_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "打开一文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFile file(fileName);
if (!file.exists()) {
qDebug() << "文件不存在";
return;
}
if (!file.open(QIODevice::ReadOnly |QIODevice::Text)) {
qDebug() << "文件打开失败";
return;
}
QTextStream stream(&file); //用文本流读取文件
stream.setAutoDetectUnicode(true); //自动检测Unicode,才能显示汉字
QString str;
while (!stream.atEnd()) {
str = stream.readLine(); //读取文件的一行文本
m_pTextEdit->appendPlainText(str);
}
file.close();
}
QTextStream::readLine()函数通过自动识别换行符来读取一行字符串。
2.QTextSTream写入文件
void MainWindow::on_btn_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "打开一文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getSaveFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFile file(fileName);
if (!file.exists()) {
qDebug() << "文件不存在";
return;
}
if (!file.open(QIODevice::WriteOnly |QIODevice::Text)) {
qDebug() << "文件打开失败";
return;
}
QTextStream stream(&file); //用文本流读取文件
stream.setAutoDetectUnicode(true); //自动检测Unicode,才能显示汉字
QString str = m_pTextEdit->toPlainText();
stream << str; //写入文本流
file.close(); //关闭文件
}
因为在写入文件时,直接使用了流的写入操作,所以,使用QTextStream进行文件读写是比较方便的。
三、解决中文乱码的问题
在使用QTextStremd读写有中文内容的文本文件时,为了能正确识别Unicode码,需要调用setAutoDetectUnicode(true)。设置QTextStream可以自动识别Unicode码,如果不做此设置,读取文件的中文可能会乱码,无法正常显示。
为了能解决Unicode的识别问题,可以在应用程序中做全局的设置,使用应用程序支持Unicode,方法是在main()函数中使用QTextCodec类进行编码设置。
示例代码如下所示:
int main(int argc, char *argv[])
{
QTextCodec *pCodec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(pCodec);
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
四、文件目录操作
1.文件目录操作相关的类
Qt为文件和目录操作提供了一些类,利用这些类可以方便的实现一些操作,Qt提供的与文件和目录操作相关的类包括以下几个:
- QCoreApplication:用于提取应用程序路径、程序名等文件信息。
- QFile:除了打开文件操作外,QFile还有复制文件、删除文件等功能。
- QFileInfo:用于提取文件的信息,包括路径、文件名、后缀等。
- QDir:用于提取目录或文件信息,获取一个目录下的文件或目录列表,创建或删除目录和文件,文件重命名等操作。
- QTemporaryDir和QTemporaryFile:用于创建临时目录和临时文件。
- QFileSystemWatcher:文件和目录监听类,监听目录下文件的添加、删除等变化,监听文件修改变化。
这些类基本覆盖了文件操作需要的主要功能,有些功能还在某些类里重复出现,例如QFile和QDir都具有删除文件、判断文件是否存在的功能。
2.QCoreApplication类
QCoreApplication是为无GUI应用提供事件循环的类,是所有应用程序类的基类,其子类QGuiApplication为GUI界面的应用程序提供流控制和主要的设定,QGuiApplication的子类QApplication为基于QWidget的应用程序提供支持,包括界面的初始化等。创建的Qt Widget Application都是基于QApplication的,在main()函数里可以看到QApplication的应用。
QCoreApplication提供了一些有用的静态函数,可以获取应用程序的名称、启动路径等信息。
/* 返回应用程序启动路径 */ qDebug() << QCoreApplication::applicationDirPath(); /* 返回应用程序的带有目录的完整文件名 */ qDebug() << QCoreApplication::applicationFilePath(); /* 返回应用程序名称,无路径、无后缀 */ qDebug() << QCoreApplication::applicationName(); /* 返回动态加载库文件时,应用程序搜索的目录列表 */ qDebug() << QCoreApplication::libraryPaths(); /* 退出应用程序 */ QCoreApplication::exit();

3.QFile类
前面使用QFile类进行文件的操作,应用了QFile::open()函数。除了打开文件提供读写操作外,QFile还有一些静态函数或成员函数用于文件操作。
QFile的一些静态函数:
QFile的一些成员函数:

4.QFileInfo类
QFileInfo类的接口函数提供文件的各种信息,QFileInfo对象创建时可以指定一个文件名作为当前文件,也可以用setFile()函数指定一个文件作为当前文件。

示例代码如下所示:
void MainWindow::on_btn_clicked()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "打开一文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFileInfo fileInfo;
fileInfo.setFile(fileName);
qDebug() << "fileInfo.absoluteFilePath():" << fileInfo.absoluteFilePath();
qDebug() << "fileInfo.absolutePath():" << fileInfo.absolutePath();
qDebug() << "fileInfo.fileName():" << fileInfo.fileName();
qDebug() << "fileInfo.filePath():" << fileInfo.filePath();
qDebug() << "fileInfo.path():" << fileInfo.path();
qDebug() << "fileInfo.size():" << fileInfo.size();
qDebug() << "fileInfo.baseName():" << fileInfo.baseName();
qDebug() << "fileInfo.completeBaseName():" << fileInfo.completeBaseName();
qDebug() << "fileInfo.suffix():" << fileInfo.suffix();
qDebug() << "fileInfo.completeSuffix():" << fileInfo.completeSuffix();
qDebug() << "fileInfo.isDir():" << fileInfo.isDir();
qDebug() << "fileInfo.isFile():" << fileInfo.isFile();
qDebug() << "fileInfo.isExecutable():" << fileInfo.isExecutable();
qDebug() << "fileInfo.exists():" << fileInfo.exists();
qDebug() << "QFileInfo::exists(fileName):" << QFileInfo::exists(fileName);
}

5.QDir类
QDir是进行目录操作的类,在创建QDir对象时传递一个目录字符串作为当前目录,然后QDir函数就可以针对当前目录或目录下的文件进行操作,下面列表是QDir的一些静态函数:
下面是QDir的一些公共接口函数:
获取目录下的目录或文件列表的函数entryList()需要传递QDir::Filter枚举类型的参数以获取不同的结果。QDir::Filter枚举类型的常用取值如下:
- QDir::AllDirs:列出所有目录名
- QDir::Files:列出所有文件
- QDir::Drives:列出所有盘符(Unix系统下无效)
- QDir::NoDotAndDotDot:不列出特殊的符号,如"."和“..”
- QDir::AllEntries:列出目录下所有项目
6.QTemporaryDir和QTemporaryFile
QTemporaryDir是用于创建、删除临时目录的类,其主要函数如下所示:
QTemporaryDir示例代码如下:
void MainWindow::on_btn_clicked()
{
QTemporaryDir tempDir;
if (tempDir.isValid()) {
// 临时目录成功创建
QString tempPath = tempDir.path();
qDebug() << "临时目录路径:" << tempPath;
} else {
qWarning() << "无法创建临时目录!";
return;
}
}
QTemporaryFile是Qt框架中用于创建临时文件的类。它可以帮助您在需要时创建一个临时文件,并在不再需要时自动删除它。
QTemporaryFile示例代码如下:
void MainWindow::on_btn_clicked()
{
QTemporaryFile tempFile;
//使用open()方法打开临时文件
if (tempFile.open()) {
// 临时文件成功打开
qDebug() << "临时文件路径:" << tempFile.fileName();
} else {
qWarning() << "无法打开临时文件!";
return;
}
//写入数据到临时文件
QTextStream stream(&tempFile);
stream << "这是一个临时文件的内容" << endl;
tempFile.close();
tempFile.remove(); // 显式删除临时文件
}
7.QFileSystemWatcher类
QFileSystemWatcher是对目录和文件进行监听的类,把某些目录或文件添加到QFileSystemWatcher对象的监听列表后,当目录下发送文件新建、删除等操作时会发生directoryChanged()信号,当监听的文件发生修改,重名等操作时,会发射fileChanged()信号,所以这个类在进行目录或文件监听时起作用。
QFileSystemWatcher的主要接口函数如下所示:
QFileSystemWatcher有两个信号,分别是目录变化和文件变化时发射的信号:
QFileSystemWatcher::directoryChanged(const QString &path); QFileSystemWatcher::fileChanged(const QString &path);
示例代码如下所示:
void MainWindow::on_btn_clicked()
{
QFileSystemWatcher *pFileSystemWatcher = new QFileSystemWatcher(this);
connect(pFileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, &MainWindow::on_directory_changed);
connect(pFileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &MainWindow::on_file_changed);
QString curPath = QDir::currentPath();
QString dlgTitle = "打开一文件";
QString filter = "程序文件(*.h *.cpp);;文本文件(*.txt);;所有文件(*.*)";
QString fileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
if (fileName.isEmpty()) {
return;
}
QFileInfo fileInfo;
fileInfo.setFile(fileName);
QString filePath = fileInfo.absolutePath();
pFileSystemWatcher->addPath(filePath); //添加监听目录
pFileSystemWatcher->addPath(fileName); //添加监听文件
}
void MainWindow::on_directory_changed()
{
qDebug() << "目录发生变化";
}
void MainWindow::on_file_changed()
{
qDebug() << "文件发生变化";
}

浙公网安备 33010602011771号