14.QT-QFile文件,QBuffer缓冲区,QDir目录,QFileSystemWatcher文件系统监视
QFile
Qt中所有与IO相关的类都继承于QIODevice,继承图如下所示:
其中QFile类便是用于文件操作的类
在QT中,将文件当做一种特殊的外部设备对待(比如:串口,usb等就是外部设备)
QT中,IO操作相关的函数接口,常用以下几种
打开设备
bool open(OpenMode mode); //打开文件成功返回true,否则返回false // mode有: // QIODevice::ReadOnly 、QIODevice::WriteOnly、QIODevice::ReadWrite // QIODevice::Append :写入的数据将会写在文件末尾 // QIODevice::Truncate :打开文件后,之前的内容将会消失(默认Truncate是打开的) //QIODevice::Text:以文本方式写入(若写"\n",在win平台上则自动被翻译为"\r\n"),否则以数据方式写入(写入的是字节)
读取数据
QByteArray read(qint64 maxSize) //从设备读取最多maxSize字节的数据 , QByteArray 类可以默认转换为QString类 QByteArray readAll(); //读出所有数据 qint64 readData ( char * data, qint64 maxSize ); //读出最多maxSize字节的数据,送到char * data里, 并返回成功写入的字节数,失败则返回-1 QByteArray QIODevice::readLine ( qint64 maxSize = 0 ); //读出一行数据
写入数据
qint64 write(const QByteArray & byteArray) //将byteArray写入设备,返回成功写入的字节数,失败则返回-1 qint64 writeData ( const char * data, qint64 len ); //从char * data里写入最多len字节的数据到设备, 并返回成功写入的字节数,失败则返回-1
关闭设备
void close();
- IO操作的本质是读写连续的存储空间数据
QT中,存取IO设备分为两种
–顺序存取设备(比如:串口)
只能从头开始顺序的读写数据,不能指定数据的读写位置
–随机存取设备(比如:文件)
可以随机定位到任意位置,进行数据读写,通过seek()函数实现
QFile文本文件操作示例
在Qt中,一个QFile对象便对应着一个文件
QFile file file("C:/Users/Administrator/Desktop/test.txt"); //创建文件对象 /*写数据*/ if( file.open(QIODevice::WriteOnly | QIODevice::Text) ) { file.write("D.T.Software\n"); file.write("Delphi Tang\n"); file.close(); } /*读数据*/ if( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { QByteArray ba = file.readLine(); QString s(ba); //将字节数组转换为字符串 qDebug() << s; file.close(); }
QFileInfo类(获取文件属性信息)
示例:
QFile file("C:/Users/Administrator/Desktop/test.txt"); QFileInfo info(file); qDebug() << info.exists(); //判断文件是否存在 qDebug() << info.isFile(); //判断这个路径是文件,还是文件夹 qDebug() << info.isReadable(); //该文件是否可读 qDebug() << info.isWritable(); //该文件是否可写 qDebug() << info.created(); //返回创建该文件的时间 qDebug() << info.lastRead(); //返回最后访问文件的时间 qDebug() << info.lastModified(); //返回最后修改文件的时间 qDebug() << info.path(); //返回该文件路径 qDebug() << info.fileName(); //返回该文件名称 qDebug() << info.suffix(); //返回该文件后缀 qDebug() << info.size(); //返回文件大小 qDebug() <<absoluteFilePath(); //返回该绝对路径
打印:
true true true true
QDateTime("周三 五月 2 09:01:04 2018") QDateTime("周三 五月 2 09:01:04 2018") QDateTime("周三 五月 2 09:02:33 2018") "C:/Users/Administrator/Desktop" "test.txt" "txt" 27 "C:/Users/Administrator/Desktop/test.txt"
QFile数据文件操作示例:
由于write和read函数只能支持char参数,如果填入数值型或QSTring型时,则需要转换:
QString str="哈哈达"; QFile file("C:/Users/Administrator/Desktop/test.hex"); /*写数据*/ if( file.open( QIODevice::WriteOnly ) ) { double i=3.1412; file.write(str.toStdString().c_str()); //QString->string->char file.write(reinterpret_cast<char *>(&i),sizeof(i)); //写入8字节数据(数值) file.close(); } /*读数据*/ if( file.open(QIODevice::ReadOnly) ) { QString s = file.read(str.toStdString().length()); qDebug() << s; double value; file.read(reinterpret_cast<char *>(&value),sizeof(value)); //读出double qDebug() << value; file.close(); }
这样转换会显得非常麻烦,所以QT提供了辅助类来简化文本文件/数据文件的读写
QTextStream、QDataStream辅助类
QTextStream
将写入的数据全部转换为可读文本(适用于文本文件)
QDataStream
将写入的数据根据类型转换为二进制数据(适用于数据文件)
注意
QDataStream在不同版本中,数据格式可能不同,所以数据文件如果要在不同版本QT程序间传递,还需要考虑版本问题:
void setVersion(int v); //设置读写版本号,比如4.7版本,则填入: QDataStream::Qt_4_7 int version(); //获取读写版本号
QTextStream使用示例
QFile file("C:/Users/Administrator/Desktop/test.txt");
/*写数据*/ if( file.open( QIODevice::WriteOnly| QIODevice::Text ) ) { QTextStream out(&file); //定义out对象,通过<<操作符向设备输出数据 out << QString("D.T.Software ")<<endl ; //将QString自动转为字符 out << QString("哈哈达") << endl; out << 5 << '*' << 6 << '=' << 5 * 6 << endl; //将数值自动转为字符 file.close(); } /*读数据*/ if( file.open(QIODevice::ReadOnly| QIODevice::Text) ) { QTextStream in(&file); //定义in对象,通过>>操作符从设备读数据 while( !in.atEnd() ) { QString str; in>>str; qDebug()<<str; //打印3次 } file.close(); }
注意: endl其实只是加了\n,由于win平台的换行符是\r\n,所以需要加上QIODevice::Text,QT便会自动将\n转为\r\n.
QDataStream使用示例
QFile file("C:/Users/Administrator/Desktop/test.txt"); if( file.open(QIODevice::WriteOnly) ) { QDataStream out(&file); out.setVersion(QDataStream::Qt_4_7); //设置版本 out << QString("D.T.Software"); out << QString("Result: "); out << 3.14; file.close(); } if( file.open(QIODevice::ReadOnly) ) { QDataStream in(&file); QString dt = ""; QString result = ""; double value = 0; in.setVersion(QDataStream::Qt_4_7); ////设置版本 in >> dt; in >> result; in >> value; qDebug() << dt; qDebug() << result; qDebug() << value; file.close(); }
QBuffer缓冲区
缓冲区的本质为一段连续的存储空间
- 缓存区分为内部和外部,外部设备便表示外部缓冲区,而 QBuffer类则表示计算机的内部缓冲区
- 在Qt中可以将缓冲区看作一种特殊的IO设备
- QTextStream,QDataStream文件流辅助类也可以直接用于操作缓冲区
QBuffer缓冲区的使用场合
- 通过进程间共享缓冲区,实现线程间不同类型的数据传递
- 可以缓冲外部设备的读写数据,比如串口数据
- 当数据读取速度小于写入速度时
QBuffer使用方法:
QByteArray array; QBuffer buffer(&array); if(buffer.open(QIODevice::WriteOnly)) { QDataStream out(&buffer); out << QString("3.1234"); out << QString("scorpio"); out << QString("1234"); out << 1.34; buffer.close(); } if(buffer.open(QIODevice::ReadOnly)) { QDataStream in(&buffer); QString name; QString a; QString b; double num; in >> a; in >> name; in >> b; in >> num; qDebug() << name; qDebug() << a; qDebug() << b; qDebug() <<num; buffer.close(); }
QDir目录
QT中提供了目录操作类QDir,QDir功能如下:
- 目录分隔符统一使用’/’
- 能够对目录进行任意操作(创建、删除、重命名)
- 能够获取指定目录中的所有条目(文件和文件夹)
- 能够使用过滤字符串获取指定条目
- 能够获取系统中的所有根目录
QDir使用方法如下:
QDir dir; QString path = ("C:/Users/Administrator/Desktop/QDir"); if(!dir.exists(path)) { dir.mkdir(path); } else { dir.cd(path); QStringList filters; //字符串列表,用来筛选文件条目 filters << "*.bmp" << "*.png"; QStringList list = dir.entryList(filters,QDir::NoDotAndDotDot|QDir::AllEntries); // QDir::NoDotAndDotDot:不要出现.和..两个条目, QDir::AllEntries:所有(文件,目录等) for(int i = 0; i < list.count(); i++) { qDebug() << list[i]; } }
来个示例,写个函数用来读取当前目录/或者文件的大小:
int Calculate_Size(QString PATH) { int size=0; QFileInfo file(PATH); if(file.isFile()) { return file.size(); } else if(file.isDir()) { QDir dir(PATH); QFileInfoList files = dir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries); qDebug()<<files.length(); for(int i=0;i<files.length();i++) { qDebug()<<files[i].absoluteFilePath(); size+=Calculate_Size(files[i].absoluteFilePath()); //递归地查找 } } return size; }
QFileSystemWatcher文件系统监视
用来监控目录或文件的状态变化
- 能够同时对多个目录/文件进行监控
- 当目录或文件发生改变时,将会触发信号
- 可以通过信号与槽的机制捕捉信号,并做出响应
QFileSystemWatcher信号函数如下所示:
void directoryChanged ( const QString & path ); //当指定的目录被修改(例如该目录里一个文件被添加、修改或删除或从磁盘删除时),这个信号就会发出。 void ileChanged ( const QString & path ); //当指定的文件被修改、重命名或从磁盘删除时,就会发出这个信号
示例
QFsWatcher.h:
#ifndef QFSWATCHER_H #define QFSWATCHER_H
#include <QObject> #include <QFileSystemWatcher> #include <QDebug> class QFsWatcher : public QObject { Q_OBJECT private : QFileSystemWatcher fs; private slots: void Dir_status( const QString & path ); void File_status( const QString & path ); public: explicit QFsWatcher(QObject *parent = 0); void addPath(const QString & path); }; #endif // QFSWATCHER_H
QFsWatcher.cpp:
#include "QFsWatcher.h" QFsWatcher::QFsWatcher(QObject *parent) : QObject(parent) { connect(&fs,SIGNAL(directoryChanged(const QString&)),this,SLOT(Dir_status(const QString&)) ); connect(&fs,SIGNAL(fileChanged(const QString&)),this,SLOT(File_status(const QString&)) ); } void QFsWatcher::Dir_status( const QString & path ) { qDebug()<<path<<": is Changed!"; } void QFsWatcher::File_status( const QString & path ) { qDebug()<<path<<": is Changed!"; } void QFsWatcher::addPath(const QString & path) { fs.addPath(path); }
main.cpp:
#include <QtCore/QCoreApplication> #include "QFsWatcher.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QFsWatcher watcher; watcher.addPath("C:/Users/Administrator/Desktop/QDir"); //监视QDir目录 watcher.addPath("C:/Users/Administrator/Desktop/text.txt"); //监视text.txt文件 return a.exec(); }
效果: