ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Qt - 文件操作

2022-07-17 09:34:45  阅读:192  来源: 互联网

标签:文件 QSettings const Qt QDir QString 操作 目录


简介

QT中的IO操作通过统一的接口简化了文件与外部设备的操作方式,QT中文件被当作一种特殊的外部设备,文件操作与外部设备操作相同。IO操作的本质是连续存储空间的数据读写。

IO设备的类型

顺序存取设备:只能从头开始顺序读写数据,不能指定数据的读写位置

随机存取设备:可以定位到任意位置进行数据的读写

 

QFile

QFile是一个用于读写文本、二进制文件和资源的I/O设备。 QFile可以单独使用,或者更方便地与QTextStream或QDataStream一起使用。

文件名通常在构造函数中传递,但它可以在任何时候使用setFileName()设置。 无论操作系统是什么,QFile都希望文件分隔符是'/'。 不支持使用其他分隔符(比如'\')。

可以使用exists()检查文件是否存在,并使用remove()删除文件。 (更高级的文件系统相关操作由QFileInfo和QDir提供。)

文件用open()打开,用close()关闭,用flush()刷新。 数据通常使用QDataStream或QTextStream读取和写入,但你也可以调用qiodevice继承的函数read(), readLine(), readAll(), write()。 QFile还继承了getChar()、putChar()和ungetChar(),它们每次只工作一个字符。

文件的大小由size()返回。 您可以使用pos()获取当前文件位置,或者使用seek()移动到新的文件位置。 如果您已经到达文件的末尾,atEnd()将返回true。

读文件

QFile file("./student.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
    return -1;
}
​
// qDebug() << QString(file.readAll());    //读取所有
file.seek(0);                           //移动文件指针到开头
while (!file.atEnd())
{
    qDebug().noquote() << QString(file.readLine());   //读取一行
}

QIODevice::Text标志告诉Qt将windows风格的行终止符("\r\n")转换为c++风格的终止符("\n")。 默认情况下,QFile假设为二进制,即它不会对存储在文件中的字节执行任何转换。

写文件

QFile file("./what.txt");
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
    qDebug() << "文件打开失败";
    return;
}
file.write("大家好,我是顽石老师");
file.write(QString(",今年%1岁了").arg(18).toUtf8());

临时文件

QTemporaryFile用于安全地创建唯一的临时文件

void tempFile()
{
    qDebug()<<QDir::tempPath();
    QTemporaryFile tempfile;
    if (!tempfile.open())
    {
        qDebug() << "打开失败"<<tempfile.errorString();
        return;
    }
    QTextStream stream(&tempfile);
    stream << "hello";
    qDebug() << tempfile.fileName();
}

 

流操作

在上面的读写文件中,我们发现操作还是太过复杂,为了简化文本文件和数据文件的读写操作,QT提供了QTextStream和QDataStream辅助类。QTextStream可将写入的数据全部转换为可读文本,QDataStream可将写入的数据根据类型转换为二进制数据。

QTextStream

QTextStream可以在QIODevice, QByteArray或QString上操作。 使用QTextStream的流操作符,可以方便地读和写单词,行和数字。 对于生成文本,QTextStream支持字段填充和对齐的格式化选项,以及数字的格式化。

class Student
{
public:
    qint64 number;
    QString name;
    QString grade;
    qreal math;
    qreal chinese;
    qreal english;
    friend QDebug& operator<<(QDebug& out, const Student& other)
    {
        out.noquote() << other.number << other.name << other.grade << other.math << other.chinese << other.english;
        return out;
    }
};
void readStudentInfo()
{
     QFile file("./student.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return -1;
    }
​
    Student stu;
    QTextStream stream(&file);
    qDebug().noquote() <<stream.readLine();
    while (!stream.atEnd())
    {
        stream >> stu.number >> stu.name >> stu.grade >> stu.math >> stu.chinese >> stu.english;
        qDebug() << stu;
    }
}
void test()
{
    QString res;
    QTextStream textstream(&res);
    textstream << "maye" << QString("冷寂") << "young";   //注意:中文要用Qstirng包起来,否则会乱码
    qDebug() <<res;
}

 

QDataStream

QByteArray data;
QDataStream stream(&data,QIODevice::ReadWrite);
stream << "image" << 1024 << "ABC";
//"[\x00\x00\x00\x06image\x00]   [\x00\x00\x04\x00]  [\x00\x00\x00\x04" "ABC\x00"] 22
qDebug() << data << data.size();

使用QDataStream串行化数据,如果数据是字符串则会在前面用4个字节表明字符串长度,如果是整数则直接存储。

QIODevice 类 - 什么是设备?

Qt文档指南

文件操作

Qt压缩和解压 zip--Qt

QFileInfo

QFileInfo类提供与系统无关的文件信息。

QFileInfo info(file);
QFileInfo info("../QFile-test/what.txt");
qDebug() << info.size();                //文件大小
qDebug() << info.absoluteFilePath();    //文件绝对路径(包括文件名)
qDebug() << info.absolutePath();        //绝对路径(不包括文件名)
qDebug() << info.absoluteDir();         //绝对路径 QDir
qDebug() << info.path();                //文件路径
qDebug() << info.filePath();            //返回文件名,包括路径(可以是绝对路径也可以是相对路径)。  
if(info.is)
if (info.isFile())  //如果是文件
{
    qDebug() << info.fileName();            //带后缀的文件名
    qDebug() << info.baseName();            //不带后缀的文件名
    qDebug() << info.suffix();              //获取文件后缀
}

 

QDir

QDir类提供对目录结构及其内容的访问。

QDir功能如下:

A、目录分隔符统一使用’/’

B、能够对目录进行任意操作(创建、删除、重命名)

bool mkdir(const QString &dirName) const
bool mkpath(const QString &dirPath) const
        
bool rmdir(const QString &dirName) const    //删除子目录(必须为空才能删除)
bool rmpath(const QString &dirPath) const   //删除路径(必须为空才能删除)
bool remove(const QString &fileName)        //删除指定文件
bool removeRecursively()                    //删除目录,包括它的所有内容 
​
bool rename(const QString &oldName, const QString &newName) //重命名

C、能够获取指定目录中的所有条目(文件和文件夹)

QFileInfoList entryInfoList(const QStringList &nameFilters, QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const
QFileInfoList entryInfoList(QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const
QStringList entryList(const QStringList &nameFilters, QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const
QStringList entryList(QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const

E、获取常用路径

//返回应用程序当前目录的绝对路径
QDir current()
QString currentPath()
​
//返回用户主目录  C:/Users/Maye
QDir home()
QString homePath()
 
//返回系统的临时目录。   
QDir temp()
QString tempPath()
    
//返回根目录列表 C:/  D:/ ...
QFileInfoList drives()
  • 计算目录的大小

    quint32 dirSize(const QString& dirName)
    {
        QDir dir(dirName);
        if (!dir.exists())
            return ~0;
        quint32 size = 0;
        for (QFileInfo& info : dir.entryInfoList(QDir::Filter::NoDotAndDotDot | QDir::Files | QDir::Dirs))
        {
            qDebug() << info.fileName();
            if (info.isFile())
            {
                size += info.size();
            }
            else
            {
                size += dirSize(info.filePath());
            }
        }
        return size;
    }

 

 

QFileSystemWatcher

简介

QFileSystemWatcher类用于提供监视文件和目录修改的接口。

QFileSystemWatcher通过监控指定路径的列表,监视文件系统中文件和目录的变更。

调用addPath()函数可以监控一个特定的文件或目录。如果需要监控多个路径,可以使用addPaths()。通过使用removePath()和removePaths()函数来移除现有路径。

QFileSystemWatcher检查添加到它的每个路径,已添加到QFileSystemWatcher的文件可以使用的files()函数进行访问,目录则使用directories()函数进行访问。

当一个文件被修改、重命名或从磁盘上删除时,会发出fileChanged()信号。同样,当一个目录或它的内容被修改或删除时,会发射directoryChanged()信号。需要注意:文件一旦被重命名或从硬盘删除,目录一旦从磁盘上删除,QFileSystemWatcher将停止监控。

注:监控文件和目录进行修改的行为会消耗系统资源。这意味着,你的进程同时监控会有文件数量的限制。一些系统限制打开的文件描述符的数量默认为256。也就是说,如果你的进程试使用addPath()和addPaths()函数添加超过256个文件或目录到文件系统将会失败。

公有函数

  • 构造函数

QFileSystemWatcher(const QStringList &paths, QObject *parent = nullptr)
QFileSystemWatcher(QObject *parent = nullptr)
  • 添加目录或文件

bool  addPath(const QString &path)
QStringList addPaths(const QStringList &paths)
  • 获取在监控的目录或文件

QStringList directories() const
QStringList files() const
  • 从监控中移除目录或文件

bool removePath(const QString &path)
QStringList removePaths(const QStringList &paths)

信号

  • 目录或文件发生改变

void directoryChanged(const QString &path)
void fileChanged(const QString &path)

示例

来实现一个文件/目录监控类型。

#include <QCoreApplication>
#include <QFileSystemWatcher>
#include <QDir>
#include <QFileInfo>
#include <QMap>
#include <QDebug>
class FileWatcher : public QObject
{
    Q_OBJECT
public:
    FileWatcher():mFileWatcher(new QFileSystemWatcher(this))
    {
        connect(mFileWatcher, &QFileSystemWatcher::directoryChanged, this, &FileWatcher::onDirChanged);
        connect(mFileWatcher, &QFileSystemWatcher::fileChanged, this, &FileWatcher::onFileChanged);
    };
    void addWatcherPath(const QString&path)
    {
        //把每个目录和文件都添加监视
        mFileWatcher->addPath(path);
        //如果监视的是目录,则把目录中的项保存起来
        if(QFileInfo(path).isDir())
            mCurContentsMap.insert(path,QDir(path).entryList(QDir::Filter::NoDotAndDotDot | QDir::Dirs | QDir::Files));
​
        //遍历子项
        QDir dir(path);
        for(QString ph : dir.entryList(QDir::Filter::NoDotAndDotDot | QDir::Dirs | QDir::Files))
        {
            if(QFileInfo(ph).isFile())
            {
                mFileWatcher->addPath(ph);
            }
            else //目录
            {
               addWatcherPath(ph);
            }
        }
    }
​
public slots:
    void onDirChanged(const QString& path)
    {
        qDebug() << path << "dirChanged"<<mFileWatcher->directories();
        //获取目录下所有项列表
        auto curEntryList = QDir(path).entryList(QDir::Filter::NoDotAndDotDot | QDir::Dirs | QDir::Files);
​
        //获取目录下原来项的列表
        auto oldEntryList = mCurContentsMap[path];
​
        //qDebug()<<"curEntryList"<<curEntryList;
        //qDebug()<<"oldEntryList"<<oldEntryList;
​
​
        //把curEntryList和oldEntryList转成集合set
        QSet<QString> curDirSet(curEntryList.begin(),curEntryList.end());
        QSet<QString> oldDirSet(oldEntryList.begin(),oldEntryList.end());
​
​
        //更新设置
        mCurContentsMap[path] = curEntryList;
​
        //判断是否修改了文件:如果新老集合大小相等,说明只是文件名改变了
        if(curDirSet.size() == oldDirSet.size())
        {
            auto modifyDir = curDirSet - oldDirSet;
            if(!modifyDir.isEmpty())
            {
                //对修改的文件进行操作
                qDebug()<<"修改"<<modifyDir;
            }
        }
        //判断是否添加了文件
        else if(curDirSet.size() > oldDirSet.size())
        {
             auto addDir = curDirSet - oldDirSet;
             if(!addDir.isEmpty())
             {
                 //对添加的文件进行操作
                 qDebug()<<"添加"<<addDir;
             }
​
        }
        //判断是否删除了文件
        else if(curDirSet.size() < oldDirSet.size())
        {
             auto delDir = curDirSet - oldDirSet;
             if(!delDir.isEmpty())
             {
                 //对删除的文件进行操作
                 qDebug()<<"删除"<<delDir;
             }
        }
    }
    void onFileChanged(const QString& file)
    {
        qDebug() << file << "fileChanged";
​
        QFileInfo info(file);
        QString strPath = info.absolutePath();
        QString strName = info.fileName();
​
        qDebug() << QString("The file %1 at path %2 is updated").arg(strName).arg(strPath);
    }
private:
    QFileSystemWatcher *mFileWatcher;
    QMap<QString,QStringList> mCurContentsMap;  //每个监控路径对应的列表
};
​
​
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
​
    FileWatcher watcher;
    watcher.addWatcherPath("./");
​
    return a.exec();
}
​
#include"main.moc"

QStandardPaths

简介

QStandardPaths类提供了访问标准路径的方法。 所谓系统标准路径指的是本地文件系统中,用户的特定目录或系统的配置目录。比如在Windows系统中的“我的文档”,“视频”,“图片”等目录位置。

对于一个大型项目,系统的标准目录是保存数据,配置信息的一个非常有用的地方。例如,一个应用程序需要将下载好的文档保存在本地文件系统的某个地方,而它不能假设某个定好的路径是存在于磁盘上的。有的人可能会将这个文档保存在应用程序所在的工作目录中,当然这是个好方法,但有时应用程序并不希望将数据放在工作目录中,这是因为:

  • 这会使得程序工作目录变得复杂,让用户来干预工作目录,这无疑是一件危险的事情,很可能会破坏程序。

  • 有的程序会希望工作目录是只读的,所以禁止其它用户来对其进行修改。

  • 如果某些配置文件是和其它程序是共享的,如若放置这些文件在某个程序的工作目录中,显然是不明智的做法,而最好的做法就是放在这些标准目录中啦。

对于系统标准目录,我们可以认定它是必然存在的(即使不存在,也可自动创建),但是不同的操作系统,可能有不一样的系统标准目录。例如“我的文档”目录位置

  • Windows:C:/Users/$username$/Documents

  • MacOs :~/Documents

  • Linux : ~/Documents

  • Android :/Documents,//Documents

  • IOS :/Documents

如果想要做跨平台的系统,像这些路径,你都得想办法获取,这只是一个我的文档,如果再加上“下载”,“图片”等标准路径,想想是不是都很麻烦。

然而,Qt却给我们提供了非常方便的类来获取这些标准目录路径,它就是马上要学习的QStandardPaths类。所有函数均为静态函数

静态公有函数

  • 返回给定位置类型的本地化显示名称,如果找不到相关位置,则返回空QString。

[static] QString displayName(QStandardPaths::StandardLocation type)
  • 在指定路径中查找名为executableName的可执行文件,如果路径为空则查找系统路径。

[static] QString findExecutable(const QString &executableName, const QStringList &paths = QStringList())
  • 在type的标准位置中查找名为fileName的文件或目录。

[static] QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = LocateFile)
  • 根据文件名fileName在type的标准位置查找所有文件或目录。

[static] QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = LocateFile)
  • 如果testMode为true,这将在QStandardPaths中启用一个特殊的“测试模式”,它将更改可写的位置以指向测试目录。 这将阻止自动测试读取或写入当前用户的配置。

[static] void setTestModeEnabled(bool testMode)
  • 返回该类型文件所属的所有目录。

[static] QStringList standardLocations(QStandardPaths::StandardLocation type)
  • 返回写入类型为文件的目录,如果无法确定位置,则返回空字符串。

[static] QString writableLocation(QStandardPaths::StandardLocation type)

 

枚举:标准位置

enum QStandardPaths::StandardLocation 描述了各种路径的位置,可用以下函数查询。

  • QString displayName(QStandardPaths::StandardLocation type)

    根据路径类型,返回对应的本地路径名称,未找到返回空QString。

    Example

    qDebug()<<QStandardPaths::displayName(QStandardPaths::DesktopLocation);
    输出:"Desktop"
  • QString writableLocation(QStandardPaths::StandardLocation type)

    根据路径类型,返回对应的本地路径,未找到返回空QString。

    Example

    qDebug()<< QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    输出:"C:/Users/Maye/Desktop"
  • QStringList standardLocations(QStandardPaths::StandardLocation type)

    根据路径类型,返回该类型对应的所有目录路径。 如果可以确定的话,目录列表从高优先级到低优先级排序。 如果type没有定义,则此列表为空

    Example

    qDebug()<<QStandardPaths::standardLocations(QStandardPaths::DataLocation);
    输出:("C:/Users/Maye/AppData/Local/test", "C:/ProgramData/test", "F:/MyCode/QtCode/build-QtCourse-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/test/debug", "F:/MyCode/QtCode/build-QtCourse-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/test/debug/data", "F:/MyCode/QtCode/build-QtCourse-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/test/debug/data/test")

在指定位置查找文件

  • QString findExecutable(const QString &executableName, const QStringList &paths = QStringList())

在指定的路径中查找名为executableName的可执行文件,如果paths为空,则在系统路径中查找。 系统路径指PATH环境变量的值。 如果存在,返回可执行文件的绝对文件路径,如果没有找到,则返回空字符串。

Example

qDebug()<<QStandardPaths::findExecutable("calc.exe");	//只要设置了path环境变量,都可以找到
qDebug()<<QStandardPaths::findExecutable("7z.exe",QStringList()<<"D:\\MySoftWare\\7-Zip");	//如果没有设置path环境变量,可以自己指定多个路径
  • QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = LocateFile)

  • QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options = LocateFile)

    根据标准目录类型,在该目录中查找名为fileName的文件或目录。 返回找到的文件或目录的完整路径(取决于options)。 如果找不到这样的文件或目录,则返回一个空字符串

Example

qDebug()<< QStandardPaths::locate(QStandardPaths::StandardLocation::DownloadLocation,"下拉.png");

 

QSettings

简介

用户通常希望应用程序在会话中记住它的设置(窗口大小和位置,选项等)。 这些信息通常存储在Windows上的系统注册表中(HKEY_CURRENT_USERSoftware/MySoft ),以及macOS和iOS上的属性列表文件中。 在Unix系统上,在缺乏标准的情况下,许多应用程序(包括KDE应用程序)使用INI文本文件。

QSettings是对这些技术的抽象,使您能够以可移植的方式保存和恢复应用程序设置。 它还支持自定义存储格式。

QSettings的API基于QVariant,因此我们可以保存很多的类型,如QString、QRect和QImage。

如果您所需要的只是一个非持久的基于内存的结构,那么可以考虑使用QMap<QString,QVariant>替代。

基本用法

创建QSettings对象时,必须传递公司或组织的名称以及应用程序的名称。 例如,如果你的程序名为QQ,而你的公司名为NiuBi,你将构造QSettings对象如下:

 QSettings setting("NiuBi","QQ");

QSettings对象既可以在堆栈上创建,也可以在堆上创建(即使用new)。 构造和销毁QSettings对象非常快。

如果你在应用程序的很多地方使用QSettings,你可能想要使用QCoreApplication::setOrganizationName()和QCoreApplication::setApplicationName()指定组织名称和应用程序名称,然后使用默认的QSettings构造函数:

QCoreApplication::setOrganizationName("NiuBi");
QCoreApplication::setOrganizationDomain("NiuBi.com");
QCoreApplication::setApplicationName("QQ");
...
QSettings settings;

QSettings存储设置。 每个设置由一对(key,value)键值对(key为QStirng类型,value为QVariant)组成。 要写入设置,可以使用setValue()。 例如:

setting.setValue("size",QSize(640,480));
qDebug()<< setting.fileName();  //获取配置文件保存位置

如果已经存在具有相同键的设置,则现有值将被新值覆盖。 为了提高效率,更改可能不会立即保存到永久存储中。 (可以调用sync()来立即提交更改。)

你可以使用value()获取设置的值:

QSize size =  setting.value("size",QSize(250,250)).value<QSize>();

如果没有指定名称的设置,QSettings返回一个空的QVariant(无效的)。你可以通过传递第二个参数给value()来指定另一个默认值(这里传了QSize(250,250),如果配置文件中没有size,就返回自己传的这个数据)。

配置文件格式

在windows下,默认为写入注册表,如果想要写入到.ini文件并保存到exe所在目录,该怎么设置呢?

QApplication::setOrganizationName("NiuBi");
QApplication::setApplicationName("QQ");
​
QSettings setting(QApplication::applicationDirPath()+"/qfile.ini" ,QSettings::Format::IniFormat);

 

公有函数

常用

  • 设置将key设置为value的值。 如果键已经存在,则覆盖前面的值。

void setValue(const QString &key, const QVariant &value)
  • 返回设置键的值。 如果该设置不存在,则返回defaultValue。

    如果没有指定默认值,则返回一个默认的QVariant。

QVariant QSettings::value(const QString &key, const QVariant &defaultValue = QVariant()) const
  • 将任何未保存的更改写入永久存储,并重新加载与此同时被另一个应用程序更改的任何设置。

    这个函数会定期从QSettings的析构函数和事件循环中自动调用,所以您通常不需要自己调用它。

void QSettings::sync()
  • 返回一个状态码,指示QSettings遇到的第一个错误,如果没有错误发生,则返回QSettings::NoError。

QSettings::Status status() const
  • 删除设置键和键的任何子设置。

void remove(const QString &key)
  • 返回使用该QSettings对象写入的设置存储的路径。

    在Windows上,如果格式为QSettings::NativeFormat,则返回值为系统注册表路径,而不是文件路径。

QString QSettings::fileName() const

分组

  • 向当前组添加前缀。

void beginGroup(const QString &prefix)
  • 将组重置为相应beginGroup()调用之前的值。

void endGroup()
  • 返回当前组。

QString QSettings::group() const
  • 向当前组添加前缀并开始从数组读取。 返回数组的大小。[有案例]

int beginReadArray(const QString &prefix)
  • 向当前组添加前缀,并开始写入大小为size的数组。 如果size为-1(默认值),则根据写入的条目的索引自动确定size。 [有案例]

void beginWriteArray(const QString &prefix, int size = -1)
  • 关闭数组

void endArray()
  • 将当前数组的索引设置为i。调用setValue()、value()、remove()和contains()等函数将对该索引处的数组项进行操作。

void setArrayIndex(int i)
 

标签:文件,QSettings,const,Qt,QDir,QString,操作,目录
来源: https://www.cnblogs.com/zhuchunlin/p/16485901.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有