QFileDevice、QFile、QSaveFile、QTemporaryFile

QFileDevice

一、描述

QFileDevice 类提供了一个用于读取和写入打开文件的接口

二、类型成员

1、enum QFileDevice::FileError:此枚举描述了 error() 函数可能返回的错误。

  • NoError:没有发生错误。
  • ReadError:读取文件时发生错误。
  • WriteError:写入文件时发生错误。
  • FatalError:发生致命错误。
  • ResourceError:资源不足(如打开的文件太多、内存不足等)
  • OpenError:文件无法打开。
  • AbortError:操作被中止。
  • TimeOutError:超时。
  • UnspecifiedError:未指定的错误。
  • RemoveError:无法删除文件。
  • RenameError:无法重命名文件。
  • PositionError:文件中的位置不能改变。
  • ResizeError:无法调整文件大小。
  • PermissionsError:无法访问文件。
  • CopyError:无法复制文件。

2、enum QFileDevice::FileHandleFlag:打开文件时使用此枚举来指定仅适用于文件而不适用于通用 QIODevice 的附加选项。

  • AutoCloseHandle:传入 open() 的文件句柄应该被 close() 关闭,默认行为是关闭文件只是刷新文件,应用程序负责关闭文件句柄。当按名称打开文件时,此标志被忽略,因为 Qt 始终拥有文件句柄并且必须关闭它。
  • DontCloseHandle:如果没有显式关闭,当 QFile 对象被销毁时,底层文件句柄保持打开状态。

3、enum QFileDevice::FileTime:该枚举由 fileTime() 和 setFileTime() 函数使用。

  • FileAccessTime:最近一次访问文件的时间(例如读取或写入)。
  • FileBirthTime:创建文件的时间(UNIX 可能不支持)。
  • FileMetadataChangeTime:上次更改文件元数据的时间。
  • FileModificationTime:最近修改文件的时间。

3、enum QFileDevice::MemoryMapFlag:此枚举描述了 map() 函数可能使用的特殊选项。

  • NoOptions:没有选项。
  • MapPrivateOption:映射的内存将是私有的,因此任何修改对其他进程都不可见,也不会写入磁盘。

4、enum QFileDevice::Permissionpermission() 函数使用此枚举来报告文件的权限和所有权。 

  • ReadOwner:文件的所有者可以读取文件。
  • WriteOwner:文件可由文件的所有者写入。
  • ExeOwner:文件可由该文件的所有者执行。
  • ReadUser:用户可以读取文件。
  • WriteUser:文件可由用户写入。
  • ExeUser:文件可由用户执行。
  • ReadGroup:文件可以被组读取。
  • WriteGroup:文件可由组写入。
  • ExeGroup:文件可由组执行。
  • ReadOther:任何人都可以读取该文件。
  • WriteOther:文件可以被任何人写入。
  • ExeOther:文件可由任何人执行。

在 NTFS 文件系统上,出于性能原因,所有权和权限检查默认是禁用的。要启用它,需包含以下行:

extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;

然后通过将 qt_ntfs_permission_lookup 递增和递减 1 来打开和关闭权限检查。

qt_ntfs_permission_lookup++; // 开启检查
qt_ntfs_permission_lookup--; // 再次关闭

创建一个文件然后设置禁止写入权限:

返回错误的权限。

 三、成员函数

1、QString fileName()

返回文件的名称。

2、QDateTime fileTime(QFileDevice::FileTime time)

      bool setFileTime(const QDateTime &newDate, QFileDevice::FileTime fileTime)

返回时间指定的文件时间。如果无法确定时间,则返回 QDateTime()(无效的日期时间)。

3、bool flush()

将任何缓冲数据刷新到文件中。返回是否刷新成功。

4、int handle()

返回文件的文件句柄。这是一个小的正整数,适用于 fdopen() 和 fcntl() 等 C 库函数。

如果文件没有打开,或者有错误,则返回 -1。

5、uchar * map(qint64 offset, qint64 size, QFileDevice::MemoryMapFlags flags = NoOptions)

从偏移量 offset 开始将文件的 size 字节映射到内存中。调用之前应该打开文件,但在映射内存后文件不需要保持打开状态。当 QFile 被销毁或使用此对象打开新文件时,任何尚未取消映射的映射都将自动取消映射。

  • 使用 NoOptions 则映射将具有与文件相同的打开模式(读取和/或写入),
  • 使用 MapPrivateOption 则始终可以写入映射的内存。

如果出现错误,则返回指向内存或 nullptr 的指针。

      bool unmap(uchar *address)

取消映射内存地址。返回是否取消映射成功。

    auto size = file.size();
    uchar* fpr = file.map(0, size); // 映射文件
    QByteArray data;
    if(fpr == nullptr)
    {
        qDebug() << "file map error:" << file.errorString();
    }
    else
    {
        data = QByteArray::fromBase64(QByteArray((char*)fpr, size));
        file.unmap(fpr);
    }

6、bool resize(qint64 sz)

设置文件大小(以字节为单位)sz。返回调整大小是否成功。

如果 sz 比当前文件大,新字节将被设置为空格字符(\u0000); 如果 sz 较小,则文件将被截断。

7、void unsetError()

将文件的错误设置为 NoError


QFile

一、描述

QFile 继承自 QFileDevice,是一种用于读写文本和二进制文件和资源的 I/O 设备,提供了读取和写入文件的接口。

QFile 可以单独使用,或者更方便地与 QTextStreamQDataStream 一起使用。

无论操作系统如何,QFile 都建议文件分隔符为 “/”。不支持使用其他分隔符(例如,'\')。

通常使用 QDataStreamQTextStream 读取和写入数据,也可以调用 QIODevice 继承的函数 read()、readLine()、readAll()、write()。

QFile 还继承了 getChar()、putChar() 和 ungetChar(),它们一次只处理一个字符。

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

1.1、直接读取文件

以下示例逐行读取文本文件:

    QFile file("in.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    while (!file.atEnd()) {
        QByteArray line = file.readLine();
        process_line(line);
    }

Text 标志告诉 Qt 将 Windows 样式的行终止符 ("\r\n") 转换为 C++ 样式的终止符 ("\n")。默认情况下,QFile 假定为二进制处理,即它不对存储在文件中的字节执行任何转换。

1.2、使用流读写文件

下一个示例使用 QTextStream 逐行读取文本文件:

    QFile file("in.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine();
        process_line(line);
    }

QTextStream 负责将存储在磁盘上的 8 位数据转换为 16 位 Unicode QString。默认情况下,它假定文件以 UTF-8 编码。这可以使用 QTextStream::setEncoding() 来设置。

要写入文本,可以使用 operator<<(),它被重载以获取左侧的 QTextStream 和右侧的各种数据类型:

    QFile file("out.txt");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;

    QTextStream out(&file);
    out << "The magic number is: " << 49 << "\n";

QDataStream 与此类似,可以使用 operator<<() 写入数据并使用 operator>>() 将其读回。

当使用 QFileQFileInfoQDir 通过 Qt 访问文件系统时,可以使用 Unicode 文件名。在 Unix 上,这些文件名被转换为 8 位编码。如果想使用标准 C++ API(<cstdio> 或 <iostream>)或特定于平台的 API 来访问文件,则可以使用 encodeName() 和 decodeName() 函数获取在 Unicode 文件名和 8位编码文件名。

在 Unix 上,有一些特殊的系统文件(例如在 /proc 中),其 size() 将始终返回 0,仍然可以从此类文件中读取数据,但是不能使用 atEnd() 来确定是否还有更多数据要读取。应该调用 readAll(),或者重复调用 read() 或 readLine(),直到无法读取更多数据。下一个示例使用 QTextStream 逐行读取 /proc/modules:

    QFile file("/proc/modules");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
    QString line = in.readLine();
    while (!line.isEmpty()) {
        process_line(line);
        line = in.readLine();
    }

1.3、信号

与其他 QIODevice 的子类不同,QFile 不会发出 aboutToClose()、bytesWritten() 或 readyRead() 信号。这个实现细节意味着 QFile 不适合读写某些类型的文件,例如 Unix 平台上的设备文件。

二、成员函数

1、bool copy(const QString &newName)

将名为 fileName() 的文件复制到 newName。返回是否复制成功。

文件在复制之前已关闭。

如果复制的文件是符号链接(symlink),则复制它所引用的文件,而不是链接本身。除了复制文件的权限之外,不会复制其他文件元数据。

如果名称为 newName 的文件已经存在,则将返回 false,即不会覆盖它。

      【static】bool copy(const QString &fileName, const QString &newName)

2、【static】QByteArray encodeName(const QString &fileName)

将 fileName 转换为由用户区域设置确定的本地 8 位编码。

      【static】QString decodeName(const QByteArray &localFileName)

encodeName() 相反,返回 localFileName 的 Unicode 版本。

3、bool exists()

返回 fileName() 指定的文件是否存在。

      【static】bool exists(const QString &fileName)

返回文件是否存在。如果 fileName 是指向不存在文件的符号链接,则返回 false。

  

4、bool link(const QString &linkName)

创建一个名为 linkName 的链接,该链接指向当前由 fileName() 指定的文件。返回是否创建成功。

链接是什么取决于底层文件系统(无论是 Windows 上的快捷方式还是 Unix 上的符号链接)。

如果将要创建的链接已存在,则 link() 将返回 false 并将 error() 设置为返回 RenameError

注意:要在 Windows 上创建有效链接,linkName 必须具有 .lnk 文件扩展名。

      【static】bool link(const QString &fileName, const QString &linkName)

5、bool moveToTrash()

fileName() 指定的文件移动到垃圾箱。如果成功则返回 true,并将 fileName() 设置为可以在垃圾箱中找到文件的路径,否则返回 false。

注意:在系统 API 不报告垃圾箱中文件位置的系统上,一旦文件被移动,fileName() 将设置为空字符串。 在没有垃圾桶的系统上,此函数始终返回 false。

      【static】bool moveToTrash(const QString &fileName, QString *pathInTrash = nullptr)

将 fileName 指定的文件移动到垃圾箱。如果成功,则返回 true,并将 pathInTrash 设置为可以在垃圾箱中找到文件的路径,否则返回false。

6、bool remove()

删除由 fileName() 指定的文件。返回删除结果。文件在被删除之前被关闭。

      【static】bool remove(const QString &fileName)

删除由 fileName 指定的文件。

7、bool rename(const QString &newName)

将当前由 fileName() 指定的文件重命名为 newName。返回是否重命名成功。

如果名称为 newName 的文件已经存在,rename() 将返回 false(即 QFile 不会覆盖它)。

该文件在重命名之前已关闭。

如果重命名操作失败,Qt 将尝试将该文件的内容复制到 newName,然后删除该文件,只保留 newName。 如果该复制操作失败或无法删除此文件,则会删除目标文件 newName 以恢复旧状态。

      【static】bool rename(const QString &oldName, const QString &newName)

8、void setFileName(const QString &name)

设置文件的名称。该名称可以没有路径、相对路径或绝对路径。

如果文件已经打开,则不要调用此函数。

如果文件名没有路径或相对路径,则使用的路径将是 open() 调用时应用程序的当前目录路径。

QFile file;
QDir::setCurrent("/tmp");
file.setFileName("readme.txt");
QDir::setCurrent("/home");
file.open(QIODevice::ReadOnly);      // 打开 "/home/readme.txt"

9、QString symLinkTarget()

   【static】QString symLinkTarget(const QString &fileName)

返回符号链接(或 Windows 上的快捷方式)指向的文件或目录的绝对路径,如果对象不是符号链接,则返回空字符串。


QSaveFile

 一、描述

QSaveFile 类提供了一个安全写入文件的接口,如果写入操作失败,则不会丢失现有数据。继承自 QFileDevice

在写入时,内容将被写入一个临时文件,与 QFile 不同,此类不允许调用 close() 而是调用 commit() 。如果未调用 commit() 并且 QSaveFile 实例被销毁,则临时文件将被丢弃。如果没有发生错误,commit() 会将其移动到最终文件中。

QSaveFile 在写入时自动检测错误,例如分区满的情况,write() 无法写入所有字节。它会记住发生了错误,并会丢弃 commit() 中的临时文件。

如果出现应用程序错误而需要中止保存,调用 cancelWriting(),这样即使稍后调用 commit() 也不会保存。

二、成员函数

1、void cancelWriting()

取消写入新文件。

如果应用程序在保存时改变主意,可以调用 cancelWriting(),这会设置一个错误代码,以便 commit() 将丢弃临时文件。

调用该方法后可以进行进一步的写操作,但是没有任何作用,写的文件会被丢弃。

2、bool commit()

如果所有先前的写入都成功,则将更改提交到磁盘。

如果写入过程中发生错误,则删除临时文件并返回 false。否则,将其重命名为最终的 fileName 并在成功时返回 true。最后,关闭设备。

3、bool directWriteFallback() / void setDirectWriteFallback(bool enabled)

如有必要,允许覆盖现有文件。

QSaveFile 在与最终文件相同的目录中创建一个临时文件并自动重命名它。但是,如果目录权限不允许创建新文件,则 open() 在无法创建临时文件时会失败。

为了允许用户在权限受限的目录中编辑具有写入权限的文件,调用 setDirectWriteFallback(true),然后 open() 可打开现有文件并写入内容而无需使用临时文件。这没有原子性保证,即应用程序崩溃或电源故障可能导致磁盘上的部分写入文件。这也意味着 cancelWriting() 在这种情况下无效。

通常,要保存用户编辑的文档,应调用 setDirectWriteFallback(true);而保存应用程序内部文件(配置文件、数据文件等)时,应保持默认设置以确保原子性。


QTemporaryFile

一、描述

QTemporaryFile 类继承自 QFile,用于安全地创建唯一的临时文件。文件本身是通过调用 open() 创建的。临时文件的名称保证是唯一的(即不会覆盖现有文件),并且该文件随后将在 QTemporaryFile 对象销毁时被删除。文件名要么是自动生成的,要么是基于模板创建的,模板被传递给 QTemporaryFile 的构造函数。

调用 close() 后重新打开临时文件是安全的。只要 QTemporaryFile 对象本身没有被破坏,唯一的临时文件就会存在并在 QTemporaryFile 内部保持打开状态。

默认文件名由 QCoreApplication::applicationName() 确定,并将放置在 QDir::tempPath() 返回的临时路径中。如果指定了文件名,则默认情况下不会将相对文件路径放置在临时目录中,而是相对于当前工作目录。

指定的文件名可以包含模板 XXXXXX(六个大写“X”字符),它将被文件名的自动生成部分替换。

二、成员函数

1、QTemporaryFile(const QString &templateName, QObject *parent)

构造一个具有模板文件名 templateName 和指定父级的 QTemporaryFile。打开临时文件后,这将用于创建唯一的文件名。

如果 templateName 不包含 XXXXXX,它将自动附加并用作文件名的动态部分。

2、~QTemporaryFile()

销毁临时文件对象,必要时自动关闭文件,如果处于自动删除模式则将自动删除文件。

3、void setAutoRemove(bool b)

设置 QTemporaryFile 是否为自动删除模式。自动删除默认是开启的。

自动删除模式将在销毁时自动从磁盘中删除文件。

4、【static】QTemporaryFile * createNativeFile(QFile &file)

       QTemporaryFile * createNativeFile(const QString &fileName)

如果 file 还不是本地文件,则在 QDir::tempPath() 中创建一个 QTemporaryFile,将 file 的内容复制到其中,并返回指向临时文件的指针,如果文件已经是本机文件,则不执行任何操作并返回 nullptr。

5、QString fileTemplate() / void setFileTemplate(const QString &name)

文件模板。默认文件模板为 QCoreApplication::applicationName().XXXXXX 并放置在 QDir::tempPath() 中。

6、bool open()

三、使用示例

    QTemporaryFile tempFile;
    tempFile.setAutoRemove(false);//删除对象后不删除文件
    QString strFileName = "F:/test_temp.txt";
    tempFile.setFileName(strFileName);
    tempFile.open();
    qDebug()<<tempFile.write("aaa");//3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值