• 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:以文本方式写入(若写"
    ",在win平台上则自动被翻译为"
    "),否则以数据方式写入(写入的是字节)

    读取数据

    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
    ");
            file.write("Delphi Tang
    ");
            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.absolutePath();      //返回该文件的目录绝对路径
        qDebug() << info.fileName();          //返回该文件名称
        qDebug() << info.suffix();            //返回该文件后缀
        qDebug() << info.size();              //返回文件大小
        qDebug() << info.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其实只是加了 ,由于win平台的换行符是 ,所以需要加上QIODevice::Text,QT便会自动将 转为 .

    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();
    }

    效果:

     

  • 相关阅读:
    Vue+ElementUI 安装与应用
    python 之serial、pyusb 使用开发
    ASP.NET Swagger 创建与汉化生成 API说明文档
    DataGridView绑定数据源后动态删除行
    MySql动态拼接SQL并动态赋值
    MySql存储过程
    DEV控件之TreeList使用
    DataGridView单元格格式化
    ajax通过PUT方式调用WEBAPI
    解决跨域session 同步问题
  • 原文地址:https://www.cnblogs.com/lifexy/p/8981196.html
Copyright © 2020-2023  润新知