9. Qt5文件及磁盘处理

第 9 章 Qt5 文件及磁盘处理

Qt 提供了QFile 类用于进行文件操作。QFile 类提供了读写文件的接口,可以读写文本文件、二进制文件和Qt 的资源文件。
处理文本文件和二进制文件,可以使用QTextStream 类和QDataStream 类。处理临时文件可以使用QTemporaryFile,获取文件信息可以使用QFilelnfo,处理目录可以使用QDir,监视文件和目录变化可以使用QFileSystemWatcher 。

9.1 读写文本文件

读写文本文件的方法通常有两种:一种是直接利用传统的QFile 类方法;另一种是利用更为方便的QTextStream 类方法。

9.1.1 使用QFile类读写文本

QFile 类提供了读写文件的接口。这里首先介绍如何使用QFile 类读写文本文件。

(CH901) 建立基于控制台工程,使用QFile 类读写文本文件。

源文件"main.cpp" 的具体实现代码如下:

#include <qapplication.h>
#include <QFile>
#include <qdebug.h>
int main(int argc, char* argv[]) {
	QApplication a(argc, argv);
	QFile file("textFile.txt");
	if (file.open(QIODevice::ReadOnly)) {
		char buffer[4096];
		qint64 lineLen = file.readLine(buffer, sizeof(buffer));
		if (lineLen != -1) {
			qDebug() << buffer;
		}
	}
	return a.exec();
}
/*
QFile file("textFile.txt"):
	打开一个文件有两种方式。一种方式是在构造函数中指定文件名;另一种方式是使用setFileName()函数设置文件名。

if( file.open(QIODevice::ReadOnly) ):
	打开文件使用open()函数,关闭文件使用close()函数。此处的open()函数以只读方式打开文件,只读方式参数为QIODevice::ReadOnly,只写方式参数为QIODevice::WriteOnly,读写参数为QIODevice::ReadWrite 。

qint64 lineLen = file.readLine(buffer, sizeof(buffer)):
	在QFile中可以使用从QIODevice中继承的readLine()函数读取文本文件的一行。
	
if(lineLen!=-1){ qDebugQ<<buffer; }:
	如果读取成功,则readLine()函数返回实际读取的字节数;如果读取失败,则返回"-1" 。
*/
9.1.2 使用QTextStream 类读写文本

QTextStream提供了更为方便的接口来读写文本,它可以操作QIODevice、QByteArray和QString 。使用QTextStream的流操作符,可以方便地读写单词、行和数字。为了产生文本,QtextStream还提供了填充、对齐和数字格式化的选项。

(CH902) 建立基于控制台的工程,使用QTextStream 类读写文本文件。

操作步骤与上节的实例类似,不再重复介绍。

源文件"main.cpp" 的具体实现代码如下:

#include <qapplication.h>
#include <QFile>
#include <qdebug.h>

int main(int argc, char* argv[]) {
	QApplication a(argc, argv);
	QFile file("textFile.txt");
	if (file.open(QFile::WriteOnly | QFile::Truncate)) {
		QTextStream out(&file);
		out << QObject::tr("score:") << qSetFieldWidth(10) << 
            left << 90 << endl;
	}
	return a.exec();
}
/*
if (file.open(QFile::WriteOnly | QFile::Truncate)):
	参数QFile::Truncate表示将原来文件中的内容清空。输出时将格式设为左对齐,占10 个字符位置。
	
out << QObject::tr("score:") << qSetFieldWidth(10) << left << 90 << endl:
	用户使用格式化函数和流操作符设置需要的输出格式。其中,qSetFieldWidth()函数是设置字段宽度的格式化函数。除此之外,QTextStream还提供了其他一些格式化函数,见表9.1。
	其中,left操作符是QTextStream定义的类似于<iostream>中的流操作符。QTextStream还提供了其他一些流操作符,见表9.2 。
*/
表9.1 QTextStream 的格式化函数
函数功能描述
qSetFieldWidth(int width)设置字段宽度
qSetPadChar(QChar ch)设置填充字符
qSetRea!NumberPercision(int precision)设置实数精度
表9.2 QTextStream 的流操作符
操作符作用描述
bin设置读写的整数为二进制数
oct设置读写的整数为八进制数
dec设置读写的整数为十进制数
hex设置读写的整数为十六进制数
showbase强制显示进制前缀,如十六进制(0x) 、八进制(o) 、二进制(0b)
forcesign强制显示符号(+, -)
forcepoint强制显示小数点
noshowbase不显示进制前缀
noforcesign不显示符号
uppercasebase显示大写的进制前缀
lowercasebase显示小写的进制前缀
uppercasedigits用大写字母表示
lowercasedigits用小写字母表示
fixed用固定小数点表示
scientific用科学计数法表示
left左对齐
right右对齐
center居中
endl换行
flush清除缓冲

在QTextStream中使用的默认编码是QTextCodec: :codecForLocale()函数返回的编码,同时能够自动检测Unicode,也可以使用QTextStream::setCodec(QTextCodec *codec) 函数设置流的编码。

9.2 读写二进制文件

QDataStrearn类提供了将二进制文件串行化的功能,用于实现C++基本数据类型,如char 、short 、int、char*等的串行化。更复杂的串行化操作则是通过将数据类型分解为基本类型来完成的。

(CH903)使用QDataStrearn 读写二进制文件。

头文件"mainwindow.h"的具体代码如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void fileFun();
};

#endif // MAINWINDOW_H

源文件"mainwindow . cpp" 的具体代码如下:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent){
    fileFun();
}

// 函数fileFun()完成主要功能,其具体代码如下:
void MainWindow::fileFun() {
    /*将二进制数据写到数据流 */						    //
    QFile file("binary.dat");
    file.open(QIODevice::WriteOnly | QIODevice::Truncate);
    QDataStream out(&file);                             // 将数据序列化
    out << QString(tr("周何骏:"));                     // 字符串序列化
    out << QDate::fromString("1996/09/25", "yyyy/MM/dd");
    out << (qint32)23;                                  // 整数序列化
    file.close();
    /*从文件中读取数据 */							    //
    file.setFileName("binary.dat");
    if(!file.open(QIODevice::ReadOnly)) {
         qDebug() << "error!";
         return;
    }
    QDataStream in(&file);                              // 从文件中读出数据
    QString name;
    QDate birthday;
    qint32 age;
    in >> name >> birthday >> age;                      // 获取字符串和整数
    qDebug() << name << birthday << age;
    file.close();
}
/*
从QFile file("binary.dat")到file.close()之间的代码段:
	每一个条目都以定义的二进制格式写入文件。Qt中的很多类型,包括QBrush、QColor、QDateTime、QFont、QPixmap、QString、QVariant等都可以写入数据流。QDataStream类写入了name(QString)、birthday(QDate)和age(qint32)这三个数据。注意,在读取时也要使用相同的类型读出。

从file.setFileName("binary.dat")到file.close()之间的代码段: 
	QDataStream类可以读取任意的以QIODevice为基类的类生成对象产生的数据,如QTcpSocket、QUdpSocket、QBuffer、QFile、QProcess等类的数据。可以使用QDataStream在QAbstractSocket一端写数据,在另一端使用QDataStream读取数据,这样就免去了烦琐的高低字节转换工作。如果需要读取原始数据,则可以使用readRawdata()函数读取数据并保存到预先定义好的char*缓冲区,写原始数据使用writeRawData()函数。读写原始数据需要对数据进行编码和解码。
*/
9.3 目录操作与文件系统

QDir类具有存取目录结构和内容的能力,使用它可以操作目录、存取目录或文件信息、操作底层文件系统,而且还可以存取Qt 的资源文件。

Qt使用"/" 作为通用的目录分隔符和URL 路径分隔符。如果在程序中使用"/" 作为目录分隔符, Qt会将其自动转换为符合底层操作系统的分隔符(如Linux使用"/",Windows 使用"\")。

QDir可以使用相对路径或绝对路径指向一个文件。isRelative()和isAbsolute()函数可以判断QDir对象使用的是相对路径还是绝对路径。如果需要将一个相对路径转换为绝对路径,则使用makeAbsolute()函数。

目录的路径可以通过path()函数返回,通过setPath()函数设置新路径。绝对路径使用absolutePath()函数返回,目录名可以使用dirName()函数获得,它通常返回绝对路径中的最后一个元素,如果QDir指向当前目录,则返回"."。目录的路径可以通过cd()和cdUp()函数改变。可以使用mkdir()函数创建目录,使用rename()函数改变目录名。

判断目录是否存在可以使用exists()函数,目录的属性可以使用isReadable()、isAbsolute()、isRelative()和isRoot()函数来获取。目录下有很多条目,包括文件、目录和符号连接,总的条目数可以使用count()函数来统计。entryList()函数返回目录下所有条目组成的字符串链表。可以使用remove()函数删除文件,使用rmdir()函数删除目录。

9.3.1 文件大小及路径获取实例

(CH904) 得到一个文件的大小和所在的目录路径。
源文件"main.cpp" 的具体代码如下:

#include <qapplication.h>
#include <QFile>
#include <QStringList>
#include <QDir>
#include <QtDebug>

qint64 du(const QString& path) {
	QDir dir(path);
	qint64 size = 0;
	foreach(QFileInfo fileInfo, dir.entryInfoList(QDir::Files)) {
		size += fileInfo.size();
	}
	foreach(QString subDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
		size += du(path + QDir::separator() + subDir);
	}
	char unit = 'B';
	qint64 curSize = size;
	if (curSize > 1024) {
		curSize /= 1024;
		unit = 'K';
		if (curSize > 1024) {
			curSize /= 1024;
			unit = 'M';
			if (curSize > 1024) {
				curSize /= 1024;
				unit = 'G';
			}
		}
	}
	qDebug() << curSize << unit << "\t" << qPrintable(path) << endl;
	return size;
}
int main(int argc, char* argv[]) {
	QApplication a(argc, argv);
	QStringList args = a.arguments();
	QString path;
	if (args.count() > 1) {
		path = args[1];
	}
	else {
		path = QDir::currentPath();
	}
	qDebug() << path << endl;
	du(path);
	return a.exec();
}
9.3.2 文件系统浏览

文件系统的浏览是目录操作的一个常用功能。本节介绍如何使用QDir 类显示文件系统目录及用过滤方式显示文件列表的方法。

(CH905) 文件系统的浏览。

在头文件"fileview.h" 中,类FileView继承自QDialog类,具体代码如下:

#ifndef FILEVIEW_H
#define FILEVIEW_H

#include <QDialog>
#include <QLineEdit>
#include <QListWidget>
#include <QVBoxLayout>
#include <QDir>
#include <QListWidgetItem>
#include <QFileInfoList>
class FileView : public QDialog {
    Q_OBJECT
public:
    FileView(QWidget *parent=0,Qt::WindowFlags f=0);
    ~FileView();
    void showFileInfoList(QFileInfoList list);
public slots:
    void slotShow(QDir dir);
    void slotDirShow(QListWidgetItem * item);
private:
    QLineEdit *fileLineEdit;
    QListWidget *fileListWidget;
    QVBoxLayout *mainLayout;
};
#endif // FILEVIEW_H

源文件"fileview.cpp" 的具体代码如下:

#include "fileview.h"
#include <QStringList>
#include <QIcon>
FileView::FileView(QWidget *parent,Qt::WindowFlags f)
    : QDialog(parent,f)
{
    setWindowTitle(tr("File View"));
    fileLineEdit = new QLineEdit(tr("/"));
    fileListWidget = new QListWidget;
    mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(fileLineEdit);
    mainLayout->addWidget(fileListWidget);
    connect(fileLineEdit,SIGNAL(returnPressed()),this,SLOT (slotShow (QDir)));
    connect(fileListWidget,SIGNAL(itemDoubleClicked (QListWidgetItem*)),
            this,SLOT(slotDirShow(QListWidgetItem*)));
    QString root = "/";
    QDir rootDir(root);
    QStringList string;
    string << "*";
    QFileInfoList list=rootDir.entryInfoList(string);
    showFileInfoList(list);
}
// 槽函数slotShow()实现了显示目录dir下的所有文件,具体内容如下:
void FileView::slotShow(QDir dir) {
    QStringList string;
    string<<"*";
    QFileInfoList list=dir.entryInfoList(string,QDir::AllEntries,
                                         QDir:: DirsFirst); //
    showFileInfoList(list);
}
/*
QFilelnfoList list=dir.entrylnfoList(string, 
									QDir::AllEntries, QDir::DirsFirst):
	QDir的entrylnfoList()方法是按照某种过滤方式获得目录下的文件列表。其函数原型如下:	

QFileInfoList entryInfoList(
    const QStringList &nameFilters, // 此参数指定了文件名的过滤方式,如"*" ".tar.gz"
    Filters filters = NoFilter,// 此参数指定了文件属性的过滤方式,如目录、文件、读写属性等       
    SortFlags sort = NoSort    // 此参数指定了列表的排序情况
) const;

其中,QDir::Filter定义了一系列的过滤方式,见表9.3。QDir::SortFlag定义了一系列排序方式,见表9.4 。
*/

// 函数showFilelnfoList()实现了用户可以双击浏览器中显示的目录进入下一级目录,或单击" .. "返回上一级目录,顶部的编辑框显示当前所在的目录路径,列表中显示该目录下的所有文件。其具体代码如下:
void FileView::showFileInfoList(QFileInfoList list) {
    fileListWidget->clear();					// 首先清空列表控件
    for(unsigned int i=0; i<list.count(); i++) {	// 
        QFileInfo tmpFileInfo=list.at(i);
        if(tmpFileInfo.isDir()) {
            QIcon icon("dir.png");
            QString fileName = tmpFileInfo.fileName();
            QListWidgetItem *tmp = new QListWidgetItem(icon,fileName);
            fileListWidget->addItem(tmp);
        } else if(tmpFileInfo.isFile()) {
            QIcon icon("file.png");
            QString fileName=tmpFileInfo.fileName();
            QListWidgetItem *tmp = new QListWidgetItem(icon,fileName);
            fileListWidget->addItem(tmp);
        }
    }
}
/*
for(unsigned int i=0; i<list.count(); i++){ …}:
	依次从QFilelnfoList 对象中取出所有项,按目录和文件两种方式加入列表控件中。
*/

// 槽函数slotDirShow()根据用户的选择显示下一级目录的所有文件。其具体实现代码如下:
void FileView::slotDirShow(QListWidgetItem * item) {
    QString str=item->text();			//将下一级的目录名保存在str中
    QDir dir;							//定义一个QDir对象
    dir.setPath(fileLineEdit->text());  //设置QDir对象的路径为当前目录路径
    dir.cd(str);                        //根据下一级目录名重新设置QDir对象的路径
    fileLineEdit->setText(dir.absolutePath());	//
    slotShow(dir);						//显示当前目录下的所有文件
}
/*
fileLineEdit->setText(dir.absolutePath()): 
	刷新显示当前的目录路径。Qdir的absolutePath()方法用于获取目录的绝对路径,即以"/"开头的路径名,同时忽略多余的"."或".."及多余的分隔符。
表9.3 QDir::Filter定义的过滤方式
过滤方式作用描述
QDir::Dirs按照过滤方式列出所有目录
QDir::AllDirs列出所有目录,不考虑过滤方式
QDir::Files只列出文件
QDir::Drives列出磁盘驱动器(UNIX 系统无效)
QDir: :NoSymLinks不列出符号连接(对不支持符号连接的操作系统无效)
QDir: :NoDotAndDotDot不列出“.”和“ … ”
QDir: :AllEntries列出目录、文件和磁盘驱动器,相当于DirslFileslDrives
QDir: :Readable列出所有具有“读”属性的文件和目录
QDir:: Writable列出所有具有“写”属性的文件和目录
QDir: :Executable列出所有具有“执行”属性的文件和目录
QDir: :Modified只列出被修改过的文件(UNIX系统无效)
QDir::Hidden列出隐藏文件(在UNIX系统下,隐藏文件的文件名以“.”开始)
QDir::System列出系统文件(在UNIX系统下指FIFO 、套接字和设备文件)
QDir::CaseSensitive文件系统如果区分文件名大小写,则按大小写方式进行过滤
表9.4 QDir::SortFlag定义的排序方式
排序方式作用描述
QDir::Name按名称排序
QDir::Time按时间排序(修改时间)
QDir::Size按文件大小排序
QDir::Type按文件类型排序
QDir:: Unsorted不排序
QDir: :DirsFirst目录优先排序
QDir::DirsLast目录最后排序
QDir: :Reversed反序
QDir: :lgnoreCase忽略大小写方式排序
QDir::LocaleAware使用当前本地排序方式进行排序
9.4 获取文件信息

QFilelnfo类提供了对文件进行操作时获得的文件相关属性信息,包括文件名、文件大小、创建时间、最后修改时间、最后访问时间及一些文件是否为目录、文件或符号链接和读写属性等。

在头文件"fileinfo.h" 中,类Filelnfo 继承自QDialog 类,此类中声明了用到的各种相关控件和函数,其具体内容如下:

#ifndef FILEINFO_H
#define FILEINFO_H

#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
class FileInfo : public QDialog
{
    Q_OBJECT
public:
    FileInfo(QWidget *parent = 0,Qt::WindowFlags f=0);
    ~FileInfo();
public slots:
    void slotFile();
    void slotGet();
private:
    QLabel *fileNameLabel;
    QLineEdit *fileNameLineEdit;
    QPushButton *fileBtn;
    QLabel *sizeLabel;
    QLineEdit *sizeLineEdit;
    QLabel *createTimeLabel;
    QLineEdit *createTimeLineEdit;
    QLabel *lastModifiedLabel;
    QLineEdit *lastModifiedLineEdit;
    QLabel *lastReadLabel;
    QLineEdit *lastReadLineEdit;
    QLabel *propertyLabel;
    QCheckBox *isDirCheckBox;
    QCheckBox *isFileCheckBox;
    QCheckBox *isSymLinkCheckBox;
    QCheckBox *isHiddenCheckBox;
    QCheckBox *isReadableCheckBox;
    QCheckBox *isWritableCheckBox;
    QCheckBox *isExecutableCheckBox;
    QPushButton *getBtn;
};

#endif // FILEINFO_H

源文件"fileinfo.cpp" 的具体内容如下:

#include "fileinfo.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QDateTime>
FileInfo::FileInfo(QWidget *parent,Qt::WindowFlags f)
    : QDialog(parent,f) {
    fileNameLabel = new QLabel(tr("文件名:"));
    fileNameLineEdit = new QLineEdit;
    fileBtn = new QPushButton(tr("文件"));
    sizeLabel = new QLabel(tr("大小:"));
    sizeLineEdit = new QLineEdit;
    createTimeLabel = new QLabel(tr("创建时间:"));
    createTimeLineEdit = new QLineEdit;
    lastModifiedLabel = new QLabel(tr("最后修改时间:"));
    lastModifiedLineEdit = new QLineEdit;
    lastReadLabel = new QLabel(tr("最后访问时间:"));
    lastReadLineEdit = new QLineEdit;
    propertyLabel = new QLabel(tr("属性:"));
    isDirCheckBox = new QCheckBox(tr("目录"));
    isFileCheckBox = new QCheckBox(tr("文件"));
    isSymLinkCheckBox = new QCheckBox(tr("符号连接"));
    isHiddenCheckBox = new QCheckBox(tr("隐藏"));
    isReadableCheckBox = new QCheckBox(tr("读"));
    isWritableCheckBox = new QCheckBox(tr("写"));
    isExecutableCheckBox = new QCheckBox(tr("执行"));
    getBtn = new QPushButton(tr("获得文件信息"));
    QGridLayout *gridLayout = new QGridLayout;
    gridLayout->addWidget(fileNameLabel,0,0);
    gridLayout->addWidget(fileNameLineEdit,0,1);
    gridLayout->addWidget(fileBtn,0,2);
    gridLayout->addWidget(sizeLabel,1,0);
    gridLayout->addWidget(sizeLineEdit,1,1,1,2);
    gridLayout->addWidget(createTimeLabel,2,0);
    gridLayout->addWidget(createTimeLineEdit,2,1,1,2);
    gridLayout->addWidget(lastModifiedLabel,3,0);
    gridLayout->addWidget(lastModifiedLineEdit,3,1,1,2);
    gridLayout->addWidget(lastReadLabel,4,0);
    gridLayout->addWidget(lastReadLineEdit,4,1,1,2);
    QHBoxLayout *layout2 = new QHBoxLayout;
    layout2->addWidget(propertyLabel);
    layout2->addStretch();
    QHBoxLayout *layout3 = new QHBoxLayout;
    layout3->addWidget(isDirCheckBox);
    layout3->addWidget(isFileCheckBox);
    layout3->addWidget(isSymLinkCheckBox);
    layout3->addWidget(isHiddenCheckBox);
    layout3->addWidget(isReadableCheckBox);
    layout3->addWidget(isWritableCheckBox);
    layout3->addWidget(isExecutableCheckBox);
    QHBoxLayout *layout4 = new QHBoxLayout;
    layout4->addWidget(getBtn);
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addLayout(gridLayout);
    mainLayout->addLayout(layout2);
    mainLayout->addLayout(layout3);
    mainLayout->addLayout(layout4);
    connect(fileBtn,SIGNAL(clicked()),this,SLOT(slotFile()));
    connect(getBtn,SIGNAL(clicked()),this,SLOT(slotGet()));
}
// 槽函数slotFile()完成通过标准文件对话框获得所需要文件的文件名功能,其具体内容如下:
void FileInfo::slotFile() {
    QString fileName = QFileDialog::getOpenFileName(this,"打开","/", "files (*)");
    fileNameLineEdit->setText(fileName);
}

// 槽函数slotGet() 通过QFilelnfo 获得具体的文件信息,其具体内容如下:
void FileInfo::slotGet() {
    QString file = fileNameLineEdit->text();
    QFileInfo info(file);			              // 根据输入参数创建一个QFileInfo对象
    qint64 size = info.size();		              // 获得QFileInfo对象的大小
    QDateTime created = info.created();           // 获得QFileInfo对象的创建时间
    QDateTime lastModified = info.lastModified(); // 获得QFileInfo对象的最后修改时间
    QDateTime lastRead = info.lastRead();         // 获得QFileInfo对象的最后访问时间
    /* 判断QFileInfo对象的文件类型属性 */
    bool isDir = info.isDir();		        // 是否为目录
    bool isFile = info.isFile();	        // 是否为文件
    bool isSymLink = info.isSymLink();		//
    bool isHidden = info.isHidden();		// 判断QFileInfo对象的隐藏属性
    bool isReadable = info.isReadable();	// 判断QFileInfo对象的读属性
    bool isWritable = info.isWritable();	// 判断QFileInfo对象的写属性
    bool isExecutable = info.isExecutable();
    //判断QFileInfo对象的可执行属性
    /* 根据上面得到的结果更新界面显示 */
    sizeLineEdit->setText(QString::number(size));
    createTimeLineEdit->setText(created.toString());
    lastModifiedLineEdit->setText(lastModified.toString());
    lastReadLineEdit->setText(lastRead.toString());
    isDirCheckBox->setCheckState(isDir?Qt::Checked: Qt::Unchecked);
    isFileCheckBox->setCheckState(isFile?Qt::Checked: Qt::Unchecked);
    isSymLinkCheckBox->setCheckState(isSymLink?Qt::Checked: Qt::Unchecked);
    isHiddenCheckBox->setCheckState(isHidden?Qt::Checked: Qt:: Unchecked);
    isReadableCheckBox->setCheckState(isReadable?Qt::Checked: Qt::Unchecked);
    isWritableCheckBox->setCheckState(isWritable?Qt::Checked: Qt::Unchecked);
    isExecutableCheckBox->setCheckState(isExecutable?Qt::Checked: Qt::Unchecked);
}
/*
bool isSymLink = info.isSymLink(): 
	判断QFilelnfo对象的文件类型属性,此处判断是否为符号连接。而symLinkTarget()方法可进一步获得符号连接指向的文件名称。
*/
FileInfo::~FileInfo() {

}

文件的所有权限可以由owner()、ownerId()、group()、groupld()等方法获得。测试一个文件的权限可以使用Permission()方法。

为了提高执行的效率,QFilelnfo可以将文件信息进行一次读取缓存,这样后续的访问就不需要持续访问文件了。但是,由于文件在读取信息之后可能被其他程序或本程序改变属性,所以QFilelnfo通过refresh()方法提供了一种可以更新文件信息的刷新机制,用户也可以通过setCaching()方法关闭这种缓冲功能。

QFilelnfo可以使用绝对路径和相对路径指向同一个文件。其中,绝对路径以"/"开头(在Windows 中以磁盘符号开头),相对路径则以目录名或文件名开头,isRelative()方法可以用来判断QFilelnfo使用的是绝对路径还是相对路径。makeAbsolute()方法可以用来将相对路径转化为绝对路径。

9.5 监视文件和目录变化

在Qt中可以使用QFileSystemWatcher类监视文件和目录的改变。在使用addPath()函数监视指定的文件和目录时,如果需要监视多个目录,则可以使用addPaths()函数加入监视。若要移除不需要监视的目录,则可以使用removePath()和removePaths()函数。

当监视的文件被修改或删除时,产生一个fileChanged()信号。如果所监视的目录被改变或删除,则产生directoryChanged()信号。

(CH907)监视指定目录功能,介绍如何使用QFileSystemWatcher。
在头文件"watcher.h"中,Watcher类继承自QWidget类,其具体内容如下:

#ifndef WATCHER_H
#define WATCHER_H

#include <QWidget>
#include <QLabel>
#include <QFileSystemWatcher>
class Watcher : public QWidget {
    Q_OBJECT

public:
    Watcher(QWidget *parent = 0);
    ~Watcher();
public slots:
    void directoryChanged(QString path);
private:
    QLabel *pathLabel;
    QFileSystemWatcher fsWatcher;
};

#endif // WATCHER_H

源文件"watcher.cpp" 的具体内容如下:

#include "watcher.h"
#include <QVBoxLayout>
#include <QDir>
#include <QMessageBox>
#include <QApplication>
Watcher::Watcher(QWidget *parent)
    : QWidget(parent) {
    QStringList args=qApp->arguments();
    QString path;
    if(args.count()>1) {
        path=args[1];
    } else {
        path=QDir::currentPath();
    }
    pathLabel = new QLabel;
    pathLabel->setText(tr("监视的目录:")+path);
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(pathLabel);
    fsWatcher.addPath(path);
    connect(&fsWatcher,SIGNAL(directoryChanged(QString)), 
            this,SLOT(directoryChanged(QString)));
}
/* 
if(args.count()>1){…}:
	读取命令行指定的目录作为监视目录。如果没有指定,则监视当前目录。
connect(&fsWatcher, SIGNAL(directoryChanged(QString)), 
		this, SLOT(directoryChanged(QString))):
	将目录的directoryChanged()信号与响应函数directoryChanged()连接。
*/

// 响应函数directoryChangedO使用消息对话框提示用户目录发生了改变,具体实现代码如下:
void Watcher::directoryChanged(QString path) {
    QMessageBox::information(NULL,tr("目录发生变化"), path);
}

Watcher::~Watcher() {

}

来源:《Qt开发及实例(第四版)》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值