文件系统和文件读写
Qt文件系统
文件读写
- 文件读写是很多应用程序的基本功能。
- 有些软件是围绕特定格式文件的处理而开发的。
Qt提供的文件操作类
- Qt提供了多种类进行文件系统操作和文件读写。
- 这些类可以获取文件信息、复制或重命名文件。
文本文件的读写
- Qt提供了读写文本文件的功能。
- 可以通过相应的类读取和写入文本文件。
二进制文件的读写
- Qt同样支持读写二进制文件。
- 使用相应的类可以实现二进制文件的读写操作。
特定格式文件的读写
- Qt支持读写XML文件和JSON文件。
- 利用这些类的功能,可以根据文件格式编写相应的文件读写程序。
自定义文件格式
- 熟悉文件操作和文件读写相关类的用法后,可以设计特定格式的文件。
- 可以根据需求自行创建新的文件格式并进行读写操作。
文件操作
Qt 提供了一套强大的框架用于文件操作,可以处理和文件系统的交互。这些类覆盖了获取文件信息、删除或复制文件、读写文件内容等各种功能。
文件操作核心类:QFile
QFile 类是所有文件操作的基础。它提供了创建、打开、关闭、读写文件等核心功能。它是 Qt 文件操作的核心类,其他类大多基于 QFile 进行扩展。
文件信息获取类:QFileInfo
QFileInfo 类用于获取文件的详细信息,如文件名、路径、大小、创建时间等。它是基于 QFile 类的扩展,提供了方便的方法来获取和设置文件的各种属性。
文件复制和移动类:QFileDevice 和 QCopyDevice
QFileDevice 是处理低级文件访问和设备访问的基础类,它是 QIODevice 的子类。虽然直接用于文件复制和移动的场景较少,但它的派生类(如 QCopyDevice)可以在复制文件时提供缓冲机制,提高复制效率。
文件流处理类:QTextStream 和 QDataStream
QTextStream 和 QDataStream 用于处理文件的读写流操作。QTextStream 主要用于文本文件的读写,提供了方便的方法来读取和写入字符串。而 QDataStream 用于二进制文件的读写,常用于处理结构化数据。
| 类/功能名称 | 描述 |
|---|---|
| QFile | 提供基本的文件操作功能,包括创建、打开、读写和关闭文件。 |
| QFileInfo | 用于获取文件的详细信息,如文件名、路径、大小、修改时间等。 |
| QFileDevice | 提供一个用于访问底层设备的接口,可以处理各种类型的设备,包括文件、套接字等。它是抽象基类,通常需要其派生类来实现具体功能。 |
| 派生类(如 QSocket 等) | 作为 QFileDevice 的派生类,提供特定设备的访问功能。在文件操作中,这些派生类可以处理如复制和缓冲等底层细节。 |
| QTextStream | 用于处理文本文件的读写操作,提供流式的接口,简化文本数据的读写过程。 |
| QDataStream | 用于处理二进制文件的读写操作,也提供流式的接口,使读写二进制数据更加简单。 |
输入输出设备类
| 类 | 父类 | 主要用途 | 功能描述 |
|---|---|---|---|
| QFile | QFileDevice | 读取和写入文件内容 | 用于在 Qt 中进行文件读写操作的基本类 |
| QFileDevice | QIODevice | 扩展文件操作,提供底层操作能力 | 提供文件交互操作的底层功能 |
| QIODevice | QObject 和 QIODeviceBase | 提供读取、写入、查找等通用设备操作接口 | 与设备交互的基类,设备包括文件、网络连接等 |
| QObject | 无 | Qt 组件模型的基石,所有 Qt 对象的基础框架 | Qt 框架的核心类,提供信号与槽机制、事件处理等功能 |
QIODevice
QIODevice 类及其相关概念
QIODevice:是所有输入输出设备(IO设备)的基础类,IO设备用于进行数据输入和输出。
文件操作相关类
- QFile:用于文件操作和文件数据读写的类,可读写任意格式的文件。
- QSaveFile:专门用于保存文件的类。
- QTemporaryFile:用于创建临时文件的类,具备自动删除功能。
网络通信相关类
- QTcpSocket:实现TCP通信的类。
- QUdpSocket:实现UDP通信的类。
串行通信和蓝牙通信相关类
- QSerialPort:用于串口通信的类,实现计算机与串口设备的通信。
- QBluetoothSocket:用于蓝牙通信的类,适用于手机和平板计算机等移动设备。
外部程序启动相关类
- QProcess:用于启动外部程序,并能给程序传递参数。
缓冲区相关类
- QBuffer:以一个QByteArray对象作为数据缓冲区,将QByteArray当作I/O设备进行读写。
文件读写操作类
1、QFile 类
QFile 是 Qt 中进行文件读写操作必须用到的基础类。它提供了一系列的接口函数来进行文件的打开、读取、写入和关闭操作。
主要操作:
- 打开文件:使用 open() 函数以不同的模式打开文件,例如只读、只写或读写模式。
- 读数据:QFile 提供了 read() 、 readAll() 等函数来读取文件内容。
- 写数据:使用 write() 、 writeData() 等函数向文件写入数据。
- 关闭文件:使用 close() 函数关闭文件。
2、QTextStream 和 QDataStream 类
Qt 提供了 QTextStream 和 QDataStream 两个类,它们用于以流的方式读写文件。这两个类需要与 QFile 搭配使用。
主要特点:
- QTextStream:用于读写文本文件,使用流操作符 "<<" 和 ">>" 可以方便地进行各种类型数据的读写,包括 Qt 的一些类的数据,如 QColor、QFont 等。
- QDataStream:用于读写二进制文件,同样使用流操作符 "<<" 和 ">>" 进行数据的读写,还可以读写二进制原始数据。
3、QIODeviceBase 类及其子类
QIODeviceBase 是 QFile、QTextStream、QDataStream 等类的基类,它定义了与设备交互的接口。QIODeviceBase 的一个子类是 QDebug,用于输出调试信息。
主要子类及用途:
- QDebug:将调试信息输出到指定设备,可以输出到文件、字符串或 console 窗口。
特定文件格式的读写
Q还提供了一些类用于读写特定格式的文件,如XML文件、JSON 文件、图片文件等。
读写XML文件
XML及其特性
XML:用于标记结构化数据的标记语言,文件与平台无关,是网络上广泛使用的数据交换格式。
Qt提供的XML处理方法
基于DOM的方法
- QDomDocument:表示整个XML文档。
- QDomNode及其子类:表示文档树结构中的节点。
- 特点:
- 将XML文档表示为树状结构。
- 在内存中保留文档对象模型,便于操作文档内容。
基于流的方法
- QXmlStreamReader:用于读取XML文件,将文件解析为一系列标记(token)。
- QXmlStreamWriter:用于写入XML文件。
- 特点:
- 易于使用。
- 与XML标准兼容性好。
示例:使用 QXmlStreamReader 读取 XML
cpp
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>
void parseXml(const QString &fileName) {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "无法打开文件:" << fileName;
return;
}
QXmlStreamReader xml(&file);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
qDebug() << "元素名称:" << xml.name().toString();
// 读取属性
for (const QXmlStreamAttribute &attr : xml.attributes()) {
qDebug() << "属性:" << attr.name().toString() << "值:" << attr.value().toString();
}
} else if (token == QXmlStreamReader::Characters) {
qDebug() << "字符内容:" << xml.text().toString();
}
}
if (xml.hasError()) {
qDebug() << "XML 错误:" << xml.errorString();
}
file.close();
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.xml";
parseXml(fileName);
return app.exec();
}
示例:使用 QXmlStreamWriter 写入 XML
cpp
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamWriter>
#include <QDebug>
void writeXml(const QString &fileName) {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "无法打开文件进行写入:" << fileName;
return;
}
QXmlStreamWriter xml(&file);
xml.setAutoFormatting(true); // 自动格式化输出
xml.writeStartDocument();
xml.writeStartElement("书籍");
xml.writeStartElement("书");
xml.writeAttribute("类型", "小说");
xml.writeCharacters("书名: 平凡的世界");
xml.writeEndElement(); // 书
xml.writeEndElement(); // 书籍
xml.writeEndDocument();
file.close();
qDebug() << "XML 文件已成功写入到" << fileName;
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.xml";
writeXml(fileName);
return app.exec();
}
说明
- 读取 XML :
- 使用 QXmlStreamReader 逐步解析 XML 文件,检查每个元素和字符内容。
- 处理元素的开始和结束,以及各属性值。
- 写入 XML :
- 使用 QXmlStreamWriter 创建 XML 文档,逐步写入元素、属性和字符内容。
- setAutoFormatting(true) 使输出的 XML 更加美观。
读写JSON文件
JSON简介
- JSON定义:JS对象标记(JavaScript object notation,JSON)是一种轻量级的数据交换格式。
- JSON用途:用于在网络或程序之间传递数据,便于数据交换和存储。
- JSON优势:相比XML,JSON文件更小,编解码难度低。
Qt中的JSON处理类
- QJsonDocument:用于读写JSON文件的类。
- QJsonArray:封装了JSON数组的类。
- QJsonObject:封装了JSON对象的类。
- QJsonValue:封装了JSON值的类。
JSON的基本数据类型
- JSON的数据有6种基本数据类型:bool、double、string、array、object、null。
操作JSON文件
使用Qt提供的JSON处理类,可以解析、修改和保存JSON文件。
- 通过QJsonDocument类可以读取和写入JSON文件
- 通过QJsonArray和QJsonObject可以操作JSON数组和对象
- 通过QJsonValue可以处理JSON的值。
示例:读取 JSON 文件
cpp
#include <QCoreApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void readJson(const QString &fileName) {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "无法打开文件:" << fileName;
return;
}
QByteArray jsonData = file.readAll();
file.close();
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
if (jsonDoc.isNull()) {
qDebug() << "JSON 数据无效";
return;
}
if (jsonDoc.isObject()) {
QJsonObject jsonObject = jsonDoc.object();
qDebug() << "读取 JSON 对象:";
for (const QString &key : jsonObject.keys()) {
qDebug() << key << ":" << jsonObject.value(key).toString();
}
} else if (jsonDoc.isArray()) {
QJsonArray jsonArray = jsonDoc.array();
qDebug() << "读取 JSON 数组:";
for (const QJsonValue &value : jsonArray) {
qDebug() << value.toString();
}
}
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.json";
readJson(fileName);
return app.exec();
}
示例:写入 JSON 文件
cpp
#include <QCoreApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
void writeJson(const QString &fileName) {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "无法打开文件进行写入:" << fileName;
return;
}
QJsonObject jsonObject;
jsonObject["name"] = "John Doe";
jsonObject["age"] = 30;
jsonObject["isStudent"] = false;
QJsonArray jsonArray;
jsonArray.append("C++");
jsonArray.append("Qt");
jsonObject["skills"] = jsonArray;
QJsonDocument jsonDoc(jsonObject);
file.write(jsonDoc.toJson());
file.close();
qDebug() << "JSON 文件已成功写入到" << fileName;
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.json";
writeJson(fileName);
return app.exec();
}
说明
- 读取 JSON :
- 使用 QFile 打开 JSON 文件,读取内容。
- 用 QJsonDocument::fromJson() 解析 JSON 数据,检查数据是否有效。
- 访问 JSON 对象或数组,并打印内容。
- 写入 JSON :
- 创建 QJsonObject 和 QJsonArray,构建正确的 JSON 结构。
- 用 QJsonDocument 保存 JSON 数据,并写入文件系统。
读写图片文件
读取图片文件
使用QImage和QPixmap直接读取图片文件
- 这两个类能够从文件中读取图片,并按图片的原始大小读取整张图片。
- 适用于简单的图片读取操作,无需特殊处理的场合。
保存图片文件
使用QImage和QPixmap的save()函数直接保存图片为文件
示例:读取和显示图片
cpp
#include <QCoreApplication>
#include <QImage>
#include <QDebug>
void loadImage(const QString &fileName) {
QImage image;
if (!image.load(fileName)) {
qDebug() << "无法加载图像:" << fileName;
return;
}
qDebug() << "图像尺寸:" << image.size();
qDebug() << "图像格式:" << image.format();
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.png";
loadImage(fileName);
return app.exec();
}
示例:将 QImage 对象保存为文件
cpp
#include <QCoreApplication>
#include <QImage>
#include <QDebug>
void saveImage(const QString &fileName) {
QImage image(100, 100, QImage::Format_RGB32);
image.fill(Qt::red); // 填充红色
if (!image.save(fileName)) {
qDebug() << "无法保存图像到:" << fileName;
} else {
qDebug() << "图像已保存:" << fileName;
}
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "output.png";
saveImage(fileName);
return app.exec();
}
说明
- 读取图像 :
- 使用 QImage::load() 方法加载图像文件。
- image.size() 返回图像的尺寸。
- image.format() 返回图像的格式。
- 保存图像 :
- 创建一个新的 QImage 实例并填充颜色。
- 使用 QImage::save() 方法将图像保存到指定位置。
使用QImageReader
QImageReader类用于在读取图片文件时提供更多的控制,比 QImage 更灵活
- 通过setScaledSize()函数,可以指定读取图片的大小,实现缩略图显示。
- 适用于需要在读取图片时进行特殊处理的场合。
QImageReader 类用于读取图像文件。它的方式来处理图像文件,包括逐行读取、判断图像格式等。
主要功能:
- 支持多种图像格式(如 PNG、JPEG、BMP 等)。
- 提供了一些控制图像读取选项,如缩放、旋转等。
- 可以判断图像的帧数(适用于动画格式)。
示例:使用 QImageReader 读取图像文件的示例。
cpp
#include <QCoreApplication>
#include <QImageReader>
#include <QImage>
#include <QDebug>
#include <QFile>
void readImage(const QString &fileName) {
QImageReader imageReader(fileName);
if (!imageReader.canRead()) {
qDebug() << "无法读取图像文件:" << fileName;
return;
}
QImage image = imageReader.read();
if (image.isNull()) {
qDebug() << "读取图像失败:" << imageReader.errorString();
return;
}
qDebug() << "图像尺寸:" << image.size();
qDebug() << "图像格式:" << image.format();
// 读取其他属性
qDebug() << "图像格式:" << imageReader.format();
qDebug() << "图像宽度:" << imageReader.size().width();
qDebug() << "图像高度:" << imageReader.size().height();
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.png"; // 替换为你的图像文件
readImage(fileName);
return app.exec();
}
说明
- 创建 QImageReader 实例:传入文件路径,创建 QImageReader 对象。
- 检查文件是否可读:使用 canRead() 方法判断文件是否可以读取。
- 读取图像:使用 read() 方法读取图像,返回 QImage 对象。
- 处理错误:如果图像为空,通过 errorString() 方法获取错误信息。
- 获取图像属性:使用 size() 和 format() 方法获取图像的尺寸和格式。
QImageWriter的使用
QImageWriter类用于保存图片时提供更多的选项,支持多种图像格式,允许设置图像的编码参数,如质量、压缩等。
- 适用于在保存图片时需要进行特殊设置的场合。
示例:使用 QImageWriter 将 QImage 保存为文件的示例。
cpp
#include <QCoreApplication>
#include <QImage>
#include <QImageWriter>
#include <QDebug>
void saveImage(const QString &fileName) {
// 创建一个简单的图像
QImage image(100, 100, QImage::Format_RGB32);
image.fill(Qt::blue); // 填充为蓝色
QImageWriter writer(fileName);
// 设置图像编写格式和参数
writer.setFormat("PNG"); // 选择格式为 PNG
writer.setQuality(100); // 设置质量(仅对JPEG有影响)
// 检查编写过程
if (!writer.write(image)) {
qDebug() << "无法保存图像到:" << fileName << writer.errorString();
} else {
qDebug() << "图像已保存:" << fileName;
}
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "output.png"; // 定义输出文件名
saveImage(fileName);
return app.exec();
}
说明
- 创建 QImageWriter 实例 :
- 传入文件路径,创建 QImageWriter 对象。
- 设置输出格式和参数 :
- 使用 setFormat() 方法设置图像格式(如 PNG)。
- 使用 setQuality() 方法调整图像质量(适用于 JPEG 格式)。
- 写入图像 :
- 使用 write() 方法将 QImage 写入文件。
- 处理错误 :
- 如果写入失败,可以通过 errorString() 方法获取错误信息。
目录与文件操作
除了文件读写的类,Qt还提供了一些类用于目录和文件操作,例如获取当前目录、新建目录、复制文件、分离文件的路径和基本文件名、判断文件是否存在等。
目录和文件操作主要涉及如下一些类。
| 类名 | 描述 | 功能/用途 |
|---|---|---|
| QCoreApplication | 提取应用程序信息 | 可提取应用程序路径、程序名等信息 |
| QFile | 文件操作类 | 可进行文件的复制、删除、重命名等操作 |
| QFileInfo | 文件信息类 | 用于获取文件的各种信息,如文件的路径、基本文件名、文件名后缀、文件大小等 |
| QDir | 目录操作类 | 用于目录信息获取和目录操作,包括新建目录、删除目录、获取目录下的文件或子目录等 |
| QTemporaryDir | 创建临时目录类 | 用于创建临时目录,临时目录可在使用后自动删除 |
| QTemporaryFile | 创建临时文件类 | 用于创建临时文件,临时文件可在使用后自动删除 |
| QFileSystemWatcher | 文件系统监视类 | 用于监视设定的目录和文件,当所监视的目录或文件出现复制、重命名、删除等操作时会发射相应的信号 |
QCoreApplication
QCoreApplication和QGuiApplication概述
- QCoreApplication:为无UI的应用程序提供事件循环的类,是所有应用程序类的基类。
- QGuiApplication:是具有GUI的应用程序类,具有主事件循环,能处理和派发来自操作系统或其他来源的事件。
QApplication类的作用
- 作为QGuiApplication的子类,QApplication为基于QWidget的应用程序提供支持,包括界面的初始化等。
- 在Qt Widget Application项目中,使用Qt Creator的向导创建的应用程序都是基于QApplication类的。
- 在应用程序的main()函数中,可以看到QApplication类的应用。
QCoreApplication的静态函数
QCoreApplication提供了一些有用的静态函数,可以获取应用程序的名称、启动路径等信息。
与应用程序信息相关的几个静态函数
| 函数/方法名称 | 返回值类型 | 描述 |
|---|---|---|
| applicationName() | QString | 获取当前应用程序的名称。这个名称通常用于显示在窗口标题或关于对话框中。 |
| applicationVersion() | QString | 获取当前应用程序的版本号。这有助于在用户界面或日志中显示应用程序的版本信息。 |
| organizationName() | QString | 获取当前应用程序的组织名称。通常用于标识应用程序的开发者或公司。 |
| organizationDomain() | QString | 获取当前应用程序的组织域名。这通常用于应用程序的设置和数据存储路径的命名。 |
| format() | QString | 获取当前应用程序的可执行文件格式,通常用于识别类别和平台差异。 |
| setAttribute() | void | 设置应用程序的属性,例如启用高 DPI 支持或使用轻量级窗口等。 |
| applicationDirPath | QString | 返回应用程序所在的目录路径。 |
| applicationFilePath | QString | 返回应用程序的完整文件路径。 |
| applicationName | QString | 返回应用程序的名称。 |
| setApplicationName | void | 设置应用程序的名称。参数:新的应用程序名称。 |
| application | QString & | 代表当前应用程序实例的引用。可能是获取或设置名称的操作。具体取决于上下文。 |
| libraryPaths | QStringList | 返回库文件的路径列表。 |
| addLibraryPath(QString &path) | void | 向库路径列表添加一个新的路径。参数:新的库路径。 |
| setOrganizationName(QString &orgName) | void | 设置组织名称。参数:新的组织名称。这通常用于标识应用程序所属的组织或公司。 |
| organizationName() | QString | 返回当前设置的组织名称。 |
| exit | void | 退出应用程序。通常用于结束程序运行。可能带有退出码或其他参数,具体取决于实现。 |
QFile
QFile 类是 Qt 中用于处理文件的主要类,它提供了对文件的读写、文件属性访问和文件操作的功能。 QFile 是一个高层次的接口,基于 QByteArray 提供了方便的文件操作方法。
常用构造函数:
cpp
QFile::QFile()
QFile::QFile(const QString &name)
常用方法
| 成员方法 | 功 能 |
|---|---|
| qint64 QFile::size() const | 获取当前文件的大小。对于打开的文件,该方法返回文件中可以读取的字节数。 |
| bool QIODevice::getChar(char *c) | 从文件中读取一个字符,并存储到 c 中。读取成功时,方法返回 true,否则返回 false。 |
| bool QIODevice::putChar(char c) | 向文件中写入字符 c,成功时返回 true,否则返回 false。 |
| QByteArray QIODevice::read(qint64 maxSize) | 从文件中一次性最多读取 maxSize 个字节,然后返回读取到的字节。 |
| qint64 QIODevice::read(char *data, qint64 maxSize) | 从文件中一次性对多读取 maxSize 个字节,读取到的字节存储到 data 指针指定的内存控件中。该方法返回成功读取到的字节数。 |
| QByteArray QIODevice::readAll() | 读取文件中所有的数据。 |
| qint64 QIODevice::readLine(char *data, qint64 maxSize) | 每次从文件中读取一行数据或者读取最多 maxSize-1 个字节,存储到 data 中。该方法返回实际读取到的字节数。 |
| qint64 QIODevice::write(const char *data, qint64 maxSize) | 向 data 数据一次性最多写入 maxSize 个字节,该方法返回实际写入的字节数。 |
| qint64 QIODevice::write(const char *data) | 将 data 数据写入文件,该方法返回实际写入的字节数。 |
| qint64 QIODevice::write(const QByteArray &byteArray) | 将 byteArray 数组中存储的字节写入文件,返回实际写入的字节数。 |
| bool QFile::copy(const QString &newName) | 将当前文件的内容拷贝到名为 newName 的文件中,如果成功,方法返回 true,否则返回 false。 copy 方法在执行复制操作之前,会关闭源文件。 |
| bool QFile::rename(const QString &newName) | 对当前文件进行重命名,新名称为 newName,成功返回 true,失败返回 false。 |
| bool QFile::remove() | 删除当前文件,成功返回 true,失败返回 false。 |
QFile使用
使用 QFile 读写文件之前必须先打开文件,调用 open() 成员方法.
plain
bool QFile::open(OpenMode mode)
mode 参数用来指定文件的打开方式
| 打开方式 | 含 义 |
|---|---|
| QIODevice::ReadOnly | 只能对文件进行读操作 |
| QIODevice::WriteOnly | 只能对文件进行写操作,如果目标文件不存在,会自行创建一个新文件。 |
| QIODevice::ReadWrite | 等价于 ReadOnly |
| QIODevice::Append | 以追加模式打开文件,写入的数据会追加到文件的末尾(文件原有的内容保留)。 |
| QIODevice::Truncate | 以重写模式打开,写入的数据会将原有数据全部清除。注意,此打开方式不能单独使用,通常会和 ReadOnly 或 WriteOnly 搭配。 |
| QIODevice::Text | 读取文件时,会将行尾结束符(Unix 系统中是 "\n",Windows 系统中是 "\r\n")转换成'\n';将数据写入文件时,会将行尾结束符转换成本地格式,例如 Win32 平台上是'\r\n'。 |
为 mode 参数一次性指定多个值,值和值之间用|分割,比如:
- QIODevice::ReadOnly | QIODevice::Text:表示只允许对文件进行读操作,读取文件时,会将行尾结束符转换为 '\n';
- QIODevice::WriteOnly | QIODevice::Text:表示只允许对文件进行写操作,将数据写入文件时,会将行尾结束符转换为本地格式;
- QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text:表示对文件进行写操作,写入的数据会存放到文件的尾部,同时数据中的行尾结束符转换为本地格式。
示例:如何使用 QFile 类读写文本文件。
cpp
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.txt";
// 写入文件
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << "Hello, QFile!" << Qt::endl;
out << "This is a simple file handling example." << Qt::endl;
file.close();
qDebug() << "File written successfully.";
} else {
qDebug() << "Failed to open file for writing.";
}
// 读取文件
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
qDebug() << line; // 输出每一行
}
file.close();
} else {
qDebug() << "Failed to open file for reading.";
}
return app.exec();
}
说明
- 写入文件 :
- 创建 QFile 对象并使用 open() 方法打开文件。
- 使用 QTextStream 写入简单文本。
- 关闭文件以完成写操作。
- 读取文件 :
- 再次打开文件,使用 QIODevice::ReadOnly 模式。
- 逐行读取并输出到控制台。
- 错误处理 :
- 使用条件语句检查文件是否成功打开,并相应输出调试信息。
运行结果:
plain
File written successfully.
"Hello, QFile!"
"This is a simple file handling example."
示例2:
cpp
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
//创建 QFile 对象,同时指定要操作的文件
QFile file("D:/demo.txt");
//对文件进行写操作
if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
qDebug()<<"文件打开失败";
}
//向文件中写入两行字符串
file.write("helloworold\n");
file.write("Qt6");
//关闭文件
file.close();
//重新打开文件,对文件进行读操作
if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
qDebug()<<"文件打开失败";
}
//每次都去文件中的一行,然后输出读取到的字符串
char * str = new char[100];
qint64 readNum = file.readLine(str,100);
//当读取出现错误(返回 -1)或者读取到的字符数为 0 时,结束读取
while((readNum !=0) && (readNum != -1)){
qDebug() << str;
readNum = file.readLine(str,100);
}
file.close();
return 0;
}
运行结果:
plain
将文件内容写入D盘的demo.txt文件,然后再读取出来
QFileInfo
QFileInfo 类是 Qt 中用于文件和目录信息获取的类。它提供了关于文件或目录的详细信息,比如路径、大小、创建时间、权限等。
QFileInfo 的主要功能
- 获取文件/目录信息:如文件名、扩展名、大小、创建时间等。
- 文件状态检查:检查文件是否存在、是否可读、可写、可执行。
- 符号链接(symlink)处理:获取真实文件路径,处理符号链接。
常用方法
- exists() : 检查文件或目录是否存在。
- fileName() : 获取文件名。
- completeBaseName() : 获取去掉扩展名的文件名。
- size() : 获取文件大小(字节)。
- lastModified() : 获取文件的最后修改时间。
- isReadable() : 检查文件是否可读。
- isWritable() : 检查文件是否可写。
示例:如何使用 QFileInfo 来获取文件的信息。
cpp
#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.txt";
QFileInfo fileInfo(fileName);
// 检查文件是否存在
if (fileInfo.exists()) {
qDebug() << "文件名:" << fileInfo.fileName();
qDebug() << "完整路径:" << fileInfo.absoluteFilePath();
qDebug() << "文件大小:" << fileInfo.size() << "字节";
qDebug() << "最后修改时间:" << fileInfo.lastModified();
// 权限检查
if (fileInfo.isReadable()) {
qDebug() << "文件可读";
} else {
qDebug() << "文件不可读";
}
if (fileInfo.isWritable()) {
qDebug() << "文件可写";
} else {
qDebug() << "文件不可写";
}
// 获取文件扩展名
qDebug() << "文件扩展名:" << fileInfo.suffix();
} else {
qDebug() << "文件不存在。";
}
return app.exec();
}
说明
- 创建 QFileInfo 对象 :
- 使用文件路径创建 QFileInfo 对象。
- 检查文件状态 :
- 使用 exists() 方法检查文件是否存在,输出相关信息。
- 获取文件属性 :
- 通过 fileName() 、 absoluteFilePath() 、 size() 和 lastModified() 获取文件的基本信息。
- 检查文件的可读和可写权限。
- 获取文件扩展名 :
- 使用 suffix() 方法获取文件的扩展名。
运行结果:
plain
文件名: "example.txt"
完整路径: "D:/Qt/QtPro/testcode/build/Desktop_Qt_6_8_0_MinGW_64_bit-Debug/example.txt"
文件大小: 56 字节
最后修改时间: QDateTime(2025-02-12 14:54:01.151 中国标准时间 Qt::LocalTime)
文件可读
文件可写
文件扩展名: "txt"
QDir
QDir 类是 Qt 中用于处理目录的类。它提供了对目录的各种操作功能,比如创建、删除、重命名目录、列出目录中的文件和子目录等。
QDir 的主要功能
- 目录操作:创建、删除、重命名目录。
- 文件和子目录列表:列出目录中的所有文件和子目录。
- 路径操作:支持相对路径和绝对路径的处理。
- 过滤器:能够根据指定的模式过滤文件和目录。
- 检查状态:检查目录是否存在、是否为空等。
常用方法
- exists() : 检查目录是否存在。
- mkdir() : 创建新目录。
- rmdir() : 删除空目录。
- entryList() : 列出目录中的文件和子目录。
- absolutePath() : 获取目录的绝对路径。
- cd() : 切换到另一个目录。
示例:如何使用 QDir 类来列出指定目录中的文件和子目录。
cpp
#include <QCoreApplication>
#include <QDir>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
// 指定要操作的目录
QString dirPath = "."; // 当前目录
QDir dir(dirPath);
// 检查目录是否存在
if (dir.exists()) {
qDebug() << "目录内容:";
// 获取当前目录下的所有文件和子目录
QStringList entries = dir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries);
// 输出目录中的每一项
for (const QString &entry : entries) {
qDebug() << entry;
}
} else {
qDebug() << "目录不存在。";
}
// 创建新目录
QString newDirPath = "new_directory";
if (dir.mkdir(newDirPath)) {
qDebug() << "成功创建目录:" << newDirPath;
} else {
qDebug() << "目录创建失败:" << newDirPath;
}
// 删除新创建的目录(需确保它为空)
if (dir.rmdir(newDirPath)) {
qDebug() << "成功删除目录:" << newDirPath;
} else {
qDebug() << "目录删除失败:" << newDirPath;
}
return app.exec();
}
说明
- 创建 QDir 对象 :
- 使用指定路径创建 QDir 对象。
- 检查目录状态 :
- 使用 exists() 方法检查目录是否存在。
- 列出目录内容 :
- 使用 entryList() 方法获取目录下的文件和子目录。
- 过滤选项 QDir::NoDotAndDotDot | QDir::AllEntries 用于排除 . 和 ... 。
- 创建和删除目录 :
- 使用 mkdir() 方法创建新目录。
- 使用 rmdir() 方法删除空目录。
运行结果:
plain
目录内容:
".qmake.stash"
".qtc_clangd"
"debug"
"example.db"
"example.txt"
"Makefile"
"Makefile.Debug"
"Makefile.Release"
"release"
成功创建目录: "new_directory"
成功删除目录: "new_directory"
QTemporaryDir
QTemporaryDir 类是 Qt 中用于创建临时目录的类,通常用于存放应用程序运行时生成的临时文件。这个类会在对象生命周期结束时自动删除临时目录,从而帮助管理临时文件。
QTemporaryDir 的主要功能:
- 创建临时目录:自动生成唯一的目录名,防止命名冲突。
- 自动清理:对象析构时,临时目录和其中的文件会自动删除。
- 路径控制:可以指定临时目录的基础路径。
常用方法
- path() : 获取临时目录的路径。
- isValid() : 检查临时目录是否成功创建。
- remove() : 手动删除临时目录及其内容。
示例代码
下面是一个简单的示例,演示如何使用 QTemporaryDir 类创建和使用临时目录。
cpp
#include <QCoreApplication>
#include <QTemporaryDir>
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
// 创建一个临时目录
QTemporaryDir tempDir;
// 检查临时目录是否成功创建
if (!tempDir.isValid()) {
qDebug() << "创建临时目录失败。";
return 1;
}
qDebug() << "临时目录路径:" << tempDir.path();
// 在临时目录中创建一个临时文件
QString tempFilePath = tempDir.path() + "/tempfile.txt";
QFile tempFile(tempFilePath);
if (tempFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "成功创建临时文件:" << tempFilePath;
QTextStream out(&tempFile);
out << "这是一个临时文件。";
tempFile.close();
} else {
qDebug() << "创建临时文件失败。";
}
// 在这里可以对临时文件进行操作
// ....
// 临时目录会在 tempDir 对象析构时自动删除
return app.exec();
}
说明
- 创建 QTemporaryDir 对象:直接实例化 QTemporaryDir 对象,以创建临时目录。
- 检查临时目录有效性:使用 isValid() 方法检查目录是否成功创建。
- 获取目录路径:使用 path() 方法获取临时目录的路径。
- 创建临时文件:在临时目录中创建一个文件,并写入一些内容。
- 自动删除: QTemporaryDir 对象析构时,会自动删除临时目录及其内容。
运行结果:
plain
临时目录路径: "C:/Users/cat/AppData/Local/Temp/testcode-uJpRKc"
成功创建临时文件: "C:/Users/cat/AppData/Local/Temp/testcode-uJpRKc/tempfile.txt"
QTemporaryFilc
QTemporaryFile 类是 Qt 中用于创建临时文件的类,类似于 QTemporaryDir ,它会在对象的生命周期结束时自动删除临时文件。使用 QTemporaryFile 可以方便地进行文件操作而无需担心清理工作。
QTemporaryFile 的主要功能
- 创建临时文件:生成一个唯一的临时文件名,防止命名冲突。
- 自动清理:对象析构时会自动删除临时文件。
- 文件操作:可以像普通文件那样读取和写入数据。
常用方法
- open() : 打开临时文件。
- path() : 获取临时文件的路径。
- isOpen() : 检查文件是否成功打开。
- remove() : 手动删除临时文件。
示例代码
下面是一个简单的示例,演示如何使用 QTemporaryFile 类创建和使用临时文件。
cpp
#include <QCoreApplication>
#include <QTemporaryFile>
#include <QDebug>
#include <QTextStream>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
// 创建一个临时文件
QTemporaryFile tempFile;
// 检查临时文件是否成功打开
if (!tempFile.open()) {
qDebug() << "临时文件创建失败。";
return 1;
}
qDebug() << "临时文件路径:" << tempFile.fileName();
// 向临时文件写入一些数据
QTextStream out(&tempFile);
out << "这是一个临时文件的示例。\n";
out << "它会在程序结束时自动删除。";
// 重置文件指针,以便读取内容
tempFile.seek(0);
// 读取并输出临时文件的内容
QString content = tempFile.readAll();
qDebug() << "临时文件内容:\n" << content;
// 临时文件会在 tempFile 对象析构时自动删除
return app.exec();
}
说明
- 创建 QTemporaryFile 对象:创建 QTemporaryFile 的实例,并调用 open() 方法。
- 检查文件是否打开:使用 isOpen() 方法检查文件是否成功打开。
- 获取文件路径:使用 fileName() 方法获取临时文件的路径。
- 写入数据:使用 QTextStream 向文件写入内容。
- 读取数据:将文件指针重置,并读取文件内容输出。
- 自动删除:当 QTemporaryFile 对象超出作用域或被销毁时,临时文件会自动删除。
运行结果:
plain
临时文件路径: "C:/Users/greatcat/AppData/Local/Temp/testcode.TNyavH"
临时文件内容:
""
QFileSystemWatcher
QFileSystemWatcher是用于监控文件系统变化的类。它可以监测文件和目录的变化事件,例如文件的创建、修改、删除等。对于需要实时响应文件变化的应用程序非常有用,比如文本编辑器、文件同步工具等。
主要功能
- 监控文件和目录:可以监控一个或多个文件和目录。
- 事件通知:当监控的文件或目录发生变化时,发出相应的信号。
- 简单易用:API 设计简洁,易于集成到应用程序中。
常用信号
- fileChanged(const QString &path) : 当监控的文件被修改时发射。
- directoryChanged(const QString &path) : 当监控的目录发生变化时发射。
示例:如何使用 QFileSystemWatcher 来监控文件和目录的变化。
cpp
#include <QCoreApplication>
#include <QFileSystemWatcher>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QFileSystemWatcher watcher;
// 要监控的文件和目录
QStringList files;
QStringList directories;
QString fileToWatch = "example.txt"; // 替换为要监控的具体文件
QString dirToWatch = "."; // 当前目录
// 添加文件和目录到监控列表
files << fileToWatch;
directories << dirToWatch;
watcher.addPaths(files);
watcher.addPaths(directories);
// 连接信号与槽
QObject::connect(&watcher, &QFileSystemWatcher::fileChanged,
[](const QString &path) {
qDebug() << "文件发生变化:" << path;
});
QObject::connect(&watcher, &QFileSystemWatcher::directoryChanged,
[](const QString &path) {
qDebug() << "目录发生变化:" << path;
});
qDebug() << "监控文件:" << fileToWatch;
qDebug() << "监控目录:" << dirToWatch;
return app.exec();
}
说明
- 创建 QFileSystemWatcher 对象:实例化 QFileSystemWatcher 对象。
- 添加要监控的路径:使用 addPaths() 方法将文件和目录添加到监控列表。
- 连接信号:使用 QObject::connect() 将信号与处理变化的槽函数连接。
- 监控变化:当文件或目录发生变化时,相应的信号会被发射,控制台将输出变化的信息。
运行结果:
plain
监控文件: "example.txt"
监控目录: "."
读写文本文件
使用QFile
读取文本文件的操作
readLine:用于从文件中读取一行文本,直到遇到换行符为止。它可以选择性地返回换行符。
readAll:用于读取文件中的所有内容并返回一个 QString。
示例:如何使用 QFile 类的 readLine() 和 readAll() 方法。
cpp
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
// 创建 QFile 对象
QFile file("example.txt"); // 替换为实际文件路径
// 打开文件以读取
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "无法打开文件";
return 1;
}
// 使用 readLine 读取文件的每一行
qDebug() << "逐行读取文件内容:";
while (!file.atEnd()) {
QString line = file.readLine();
qDebug() << line.trimmed(); // 去掉行末的换行符
}
// 重置文件指针
file.seek(0);
// 使用 readAll 读取整个文件
qDebug() << "\n读取整个文件内容:";
QString allContent = file.readAll();
qDebug() << allContent;
// 关闭文件
file.close();
return app.exec();
}
说明
- 打开文件:使用 open() 方法以读模式打开文件。
- 逐行读取内容:使用 readLine() 方法逐行读取文件内容,并使用 trimmed() 去除行末的换行符。
- 重置文件指针:使用 seek(0) 方法将文件指针重置到文件开头,以便再次读取。
- 读取全部内容:使用 readAll() 方法读取整个文件的内容,并输出。
- 关闭文件:最后使用 close() 关闭文件。
运行结果:
plain
逐行读取文件内容:
"Hello, QFile!"
"This is a simple file handling example."
读取整个文件内容:
"Hello, QFile!\nThis is a simple file handling example.\n"
写入文本文件的操作
要将一个QString 字符串写入文本文件,一般是先将QString 字符串转换为QByteArray字节数组,再用函数QFile::write(QByteArray &data)将字节数组数据写入文件。
示例:
cpp
#include <QFile>
#include <QString>
#include <QByteArray>
#include <QDebug>
void writeQStringToFile(const QString &str, const QString &filePath) {
// 将 QString 转换为 QByteArray(UTF-8 编码)
QByteArray ba = str.toUtf8();
// 创建 QFile 对象并打开文件以写入数据
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "无法打开文件进行写入";
return;
}
// 将 QByteArray 数据写入文件
if (file.write(ba) == -1) { // 如果写入失败,返回 -1
qDebug() << "写入文件时出错";
file.close(); // 确保关闭文件(即使出错)
return;
}
qDebug() << "字符串已成功写入文件";
file.close(); // 关闭文件以确保所有数据都已写入磁盘
}
QSaveFile
QSaveFile类的定位:
- QSaveFile是Qt中与QFile并列的一个类,专门用于保存文件。
- 可保存文本文件或二进制文件。
QSaveFile的工作机制:
- 在保存文件时,QSaveFile会在目标文件所在的目录下创建一个临时文件。
- 写入数据首先进入临时文件。
- 若写入操作无误,通过调用QSaveFile的commit()函数,临时文件里的内容会被移至目标文件,随后临时文件会被删除。
QSaveFile的优势:
- 通过使用临时文件的方式,可以避免在写入操作出现错误时,目标文件只保存部分数据,从而保护文件结构不被破坏。
- 提供了数据的安全保存机制,即使程序异常结束,目标文件也不会有任何损失。
关于close()函数的注意事项:
- 在QSaveFile中,close()函数被设置为私有函数,因此不能再直接调用close()。
应用场景:
- QSaveFile适用于需要安全保存文件内容的场景,特别是在数据写入过程中可能存在风险的情况下。
示例:
cpp
#include <QCoreApplication>
#include <QSaveFile>
#include <QTextStream>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.txt"; // 要保存的文件
QSaveFile saveFile(fileName);
// 尝试打开文件以写入
if (!saveFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "无法打开文件进行写入:" << saveFile.errorString();
return 1;
}
// 写入数据
QTextStream out(&saveFile);
out << "这是一个安全保存文件的示例。\n";
out << "如果发生错误,原文件将不受影响。";
// 提交更改,会替换原文件
if (!saveFile.commit()) {
qDebug() << "提交失败:" << saveFile.errorString();
return 1; // 若提交失败,原文件不会被修改
}
qDebug() << "文件已成功保存到" << fileName;
return app.exec();
}
说明
- 创建 QSaveFile 对象:创建 QSaveFile 实例并传入目标文件名。
- 打开文件:使用 open() 方法以写入模式打开文件,并检查是否成功。
- 写入数据:使用 QTextStream 将数据写入文件。
- 提交更改:通过 commit() 方法将临时文件替换成目标文件,确保数据安全写入。
- 错误处理:在写入或提交失败时,输出错误信息并返回。
运行结果:
plain
文件已成功保存到 "example.txt"
QTextStream
QTextStream 是用于简化文本输入和输出的类。它提供了对文本数据的读取和写入操作,支持多种字符编码,且易于使用,适合处理文本文件、字符串和其他 I/O 流。
- QTextStream 还提供了很多读写文件相关的方法,可以设定写入到文件中的数据格式,比如对齐方式、写入数字是否带前缀等等。
常用属性:
| 属性 | 描述 |
|---|---|
| device() | 返回与当前 QTextStream 关联的设备(如文件、字符串等)。 |
| autoDetectUnicode() | 获取或设置是否自动检测 Unicode 编码。 |
| codec() | 返回当前流使用的编解码器。 |
| status() | 返回流的状态,指示是否发生了错误。 |
| locale() | 返回当前流使用的区域设置,用于格式化数字和日期。 |
| setCodec() | 设置流的编解码器,支持多种字符编码。 |
| setLocale() | 设置流的区域设置。 |
| setAutoDetectUnicode() | 设置是否启用自动检测 Unicode 编码。 |
常用方法
| 方法 | 描述 |
|---|---|
| readLine() | 从流中读取一行文本,返回字符串。 |
| readAll() | 从流中读取所有文本,返回字符串。 |
| write() | 将文本写入流中,返回写入的字符数。 |
| flush() | 刷新流,确保所有数据写入目标设备。 |
| operator<<() | 允许使用流插入操作符(<<)写入文本到流中。 |
| operator>>() | 允许使用流提取操作符(>>)从流中读取文本。 |
| setCodec() | 设置流的编解码器,指定字符编码类型。 |
| setLocale() | 设置流的区域设置,用于格式化输出。 |
| status() | 返回流的当前状态,指示是否存在错误。 |
| autoDetectUnicode() | 获取或设置自动检测 Unicode 的功能。 |
示例:如何使用 QTextStream 读取和写入文本文件。
cpp
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDebug>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QString fileName = "example.txt";
// 写入示例
QFile writeFile(fileName);
if (!writeFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "无法打开文件进行写入:" << writeFile.errorString();
return 1;
}
QTextStream out(&writeFile);
out << "Hello, QTextStream!\n";
out << "这是一个文本流写入示例。\n";
writeFile.close(); // 关闭文件
// 读取示例
QFile readFile(fileName);
if (!readFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "无法打开文件进行读取:" << readFile.errorString();
return 1;
}
QTextStream in(&readFile);
while (!in.atEnd()) {
QString line = in.readLine(); // 逐行读取
qDebug() << line; // 打印读取的行
}
readFile.close(); // 关闭文件
return app.exec();
}
说明
- 创建 QFile 对象 :
- 创建 QFile 对象用于指定要读写的文件。
- 打开文件 :
- 使用 open() 方法以写入模式打开文件,如果失败则输出错误信息。
- 写入数据 :
- 使用 QTextStream 向文件中写入文本。
- 关闭文件 :
- 完成写入后,关闭文件以释放资源。
- 读取数据 :
- 重新打开同一文件,以读取模式打开。
- 使用 readLine() 方法逐行读取文件内容,并打印到控制台。
运行结果:
plain
Hello, QTextStream!
示例2:
cpp
#include <QFile>
#include <QDebug>
#include <QString>
#include <QTextStream>
int main(int argc, char *argv[])
{
//创建 QFile 对象,同时指定要操作的文件
QFile file("D:/demo.txt");
//对文件进行写操作
if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
qDebug()<<"文件打开失败";
}
QTextStream out(&file);
//向文件中写入两行字符串
out << (QString)"helloworld\n" << (QString)"Qt6";
//关闭文件
file.close();
//重新打开文件,对文件进行读操作
if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
qDebug()<<"文件打开失败";
}
QTextStream in(&file);
//一直读,直至读取失败
while(!in.atEnd()){
QString str;
//从文件中读取一个字符串
in >> str;
qDebug() << str;
}
file.close();
return 0;
}
运行结果:
plain
helloworld
示例3:
cpp
#include <QFile>
#include <QDebug>
#include <QString>
#include <QTextStream>
int main(int argc, char *argv[])
{
QFile file("D:/demo.txt");
if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
qDebug()<<"文件打开失败";
}
QTextStream out(&file);
//将 10 的十六进制数写入文件
out << hex << 10;
//设置每份数据占用 10 个字符的位置
out.setFieldWidth(10);
//以右对齐的方式写入 3.14
out << left << 3.14;
//后续数据以左对齐的方式写入文件
out.setFieldAlignment(QTextStream::AlignRight);
out << 2.7;
//关闭文件
file.close();
return 0;
}
运行结果:
plain
a3.14 2.7
读写二进制文件
文件可以分为文本文件和二进制文件。除了文本文件,其他文件都可以看作二进制文件。
- QFile是Qt框架中用于文件操作的基础类,可以用于读写二进制文件。
- QDataStream提供了丰富的接口函数,结合QFile使用可以更便捷地读写二进制文件。
示例:
cpp
#include <QFile>
#include <QDebug>
int main(int argc, char *argv[])
{
//指定要写入文件的数据
qint32 nums[5]={1,2,3,4,5};
//写入文件之前,要将数据以二进制方式存储到字节数组中
QByteArray byteArr;
byteArr.resize(sizeof(nums));
for(int i=0;i<5;i++){
//借助指针,将每个整数拷贝到字节数组中
memcpy(byteArr.data()+i*sizeof(qint32),&(nums[i]),sizeof(qint32));
}
//将 byteArr 字节数组存储到文件中
QFile file("D:/demo.dat");
file.open(QIODevice::WriteOnly);
file.write(byteArr);
file.close();
//再次打开文件,读取文件中存储的二进制数据
file.open(QIODevice::ReadOnly);
QByteArray resArr = file.readAll();
//输出读取到的二进制数据
qDebug()<<"resArr: "<<resArr;
//将二进制数据转化为整数
char* data = resArr.data();
while(*data){
qDebug() << *(qint32*)data;
data += sizeof(qint32);
}
return 0;
}
运行结果:demo.dat 文件中会存储 {1,2,3,4,5} 这 5 个整数的二进制形式
plain
resArr: "\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00"
1
2
3
4
5
文件的基础知识
二进制文件
- 除了文本文件外,其他按照特定格式定义读写操作的文件称为二进制文件。比如JPG图片文件、PDF文件、SEGY地震数据文件等。
- 使用二进制形式保存也比使用文本文件更节省存储空间。
二进制文件的格式
- 写入与读取:写入文件时,需按照特定的顺序写入数据;读取时,也需按照相应的顺序从文件中读取。
字节序
- 定义:字节序指的是多字节数据的各个字节码在内存或文件中的存储顺序。
- 分类:大端字节序与小端字节序。
- 特点:大端字节序 :高位字节在前(低地址),低位字节在后(高地址)。小端字节序:低位字节在前(低地址),高位字节在后(高地址)。
内存中的数据字节序与CPU类型、操作系统之间的关系
内存中的数据字节序与CPU类型和操作系统
- 内存中的数据字节序与CPU类型和操作系统有关。
常见CPU类型的字节序
- Intel x86、AMD64、ARM处理器全采用小端字节序。
- MIPS采用大端字节序。
数据写入文件时的字节序设定
- 一般使用与操作系统一致的字节序,但也可以不一致。
- 以Windows系统为例,其采用的是小端字节序,但在保存数据到文件时也可以保存为大端字节序形式。
QDataStream
读写二进制的两种方法
QFile 类:
- QFile 类可以用于读写二进制文件。
- 使用 QFile 的 read() 和 write() 函数可以进行基本的读写操作。但这种方式的缺点是使用起来不太方便。
QDataStream 类:
- QDataStream 类为读写二进制文件提供了丰富的接口函数,使读写操作更加便捷和灵活。
- 当将 QFile 和 QDataStream 类结合使用时,可以更好地处理二进制文件的读写操作。
QDataStream
QDataStream是一个用于进行二进制流数据读写操作的类。这种流数据格式与CPU类型、操作系统无关,是完全独立的。
- QDataStream可以用于处理多种类型的I/O设备数据读写操作。
创建 QDataStream 对象的基本步骤:
- 首先创建一个 QFile 对象,并指定要读写的文件路径。
- 打开这个文件对象(可以使用 QFile 的 open() 函数)。
- 创建 QDataStream 对象,并关联到之前创建的 QFile 对象上。这样就可以使用 QDataStream 提供的接口函数进行读写操作了。
QDataStream的应用场景
- 二进制文件读写操作:QDataStream可以用于读取和写入二进制文件。
- 网络通信:QDataStream可以用于网络通信中的数据读写操作。
- 串口通信:QDataStream也可以用于串口通信等I/O设备的数据读写操作。
QDataStream与物理文件的关联
如果QDataStream用于二进制文件的读写操作,那么在创建QDataStream对象时,需要传递一个QFile对象作为参数。这样,QDataStream就可以与物理文件关联,实现文件的读写操作。
QDataStream流化数据的两种方式
数据流编码可以采用两种方式:
- 使用Qt的预定义编码方式
- 使用原始二进制数据方式这种数据流方式可以实现数据的序列化和反序列化,并且与操作系统、CPU类型和字节序无关。
常用属性:
| 常用属性 | 描述 |
|---|---|
| device() | 返回与当前 QDataStream 关联的设备(例如文件或内存)。 |
| status() | 返回流的当前状态,指示是否发生了错误。 |
| byteOrder() | 获取或设置字节顺序(大端或小端)。 |
| setByteOrder() | 设置流的字节顺序,影响数据存储和读取的格式。 |
| version() | 获取当前数据流的版本,影响序列化和反序列化的格式。 |
常用方法:
| 成员方法 | 功 能 |
|---|---|
| bool QDataStream::atEnd() const | 判断是否读到文件末尾,如果已经达到末尾,返回 true,否则返回 false。 |
| QDataStream &QDataStream::readBytes(char *&s, uint &l) | 对于用 writeBytes() 方法写入文件的 l 和 s,只能使用 readBytes() 方法读取出来。 |
| int QDataStream::readRawData(char *s, int len) | 从文件中读取最多 len 字节的数据到 s 中,返回值表示实际读取的字节数。注意,调用该方法之前,需要先给 s 参数分配好内存空间。 |
| void QDataStream::setVersion(int v) | 不同版本的 Qt 中,同名称的数据类型也可能存在差异,通过调用此方法手动指定版本号,可以确保读取数据的一致性。 |
| int QDataStream::skipRawData(int len) | 跳过文件中的 len 个字节,返回实际跳过的字节数。 |
| QDataStream &QDataStream::writeBytes(const char *s, uint len) | 将长度 len 和 s 一起写入到文件中,对于 writeBytes() 写入的数据,只能用 readBytes() 方法读取。 |
| int QDataStream::writeRawData(const char *s, int len) | 将 s 中前 len 字节的数据写入文件,返回值表示成功写入的字节数。 |
示例:
cpp
#include <QFile>
#include <QDebug>
#include <QDataStream>
int main(int argc, char *argv[])
{
//指定要写入文件的数据
qint32 nums[5]={1,2,3,4,5};
QFile file("D:/demo.dat");
file.open(QIODevice::WriteOnly);
//创建 QDataStream 对象
QDataStream out(&file);
//将 nums 数组中的整数逐个写入到二进制文件中
for(int i=0;i<5;i++){
out << nums[i];
}
file.close();
//再次打开文件,读取文件中存储的二进制数据
file.open(QIODevice::ReadOnly);
QDataStream in(&file);
//读取二进制文件中的数据
while(!in.atEnd()){
//每次读取一个整数
qint32 num;
in >> num;
qDebug() << num;
}
return 0;
}
输出结果:
plain
1
2
3
4
5
Qt的预定义编码方式
QDataStream的预定义编码方式:
Qt的QDataStream提供了一种预定义的编码方式,能够将基本类型的数据和简单的Qt类序列化为二进制数据。
这种方式通过将数据结构转化为二进制格式,可以方便地进行数据的存储、传输和交换。
QDataStream的数据流操作:
QDataStream主要通过流写入操作符"<<"和流读取操作符">>"进行数据序列化写入和读取。
这些操作符允许开发者以流的形式将数据写入文件或从文件中读取数据。例如,流写入操作符"<<"支持多种参数形式,可以用于写入不同类型的数据。
QDataStream的使用示例:
在使用QDataStream进行数据读写时,通常需要与文件操作类(如QFile)结合使用。
- 首先,通过打开文件创建一个QFile对象。
- 然后创建QDataStream对象并与该文件对象关联。
- 接着,可以使用流操作符进行数据的写入和读取操作。
原始二进制数据方式
QDataStream读写原始二进制数据的函数
QDataStream中用于直接读写原始二进制数据的两组函数:writeRawData()和readRawData(),以及writeBytes()和readBytes()。这些函数允许开发者完全控制文件内每字节数据的含义,使得文件格式可以被任何编程语言读写。
writeRawData()和readRawData()函数
- 这两组函数用于将原始数据写入QDataStream或从QDataStream中读取原始数据。
- writeRawData()接受一个字符指针和一个整数,分别代表要写入的数据和数据的字节数。它不会自动处理特定的结束符,也不受QDataStream的字节序设置影响,只是简单地连续写入相应字节数的数据。而readRawData()则从数据流中读取指定长度的数据到预先分配的内存中。
- 应用场景:这两个函数特别适合于写入和读取固定字节数的数据类型,如整数、浮点数等。因为这些类型的数据字节数是确定的,使用这两个函数可以确保数据的完整性和准确性。
writeBytes()和readBytes()函数
- writeBytes()在写入数据前,会先将要写入的字节数以uint类型序列化,并写入到数据的前面。这样,在读取数据时,可以通过读取这个uint值来确定接下来要读取的字节数。readBytes()则用于从流中读取数据,首先读取前面的uint值,然后根据该值读取相应的数据。
- writeBytes()除了接受数据指针和字节数外,还会自动处理长度前缀的写入。这对于写入如字符串之类的可变长度数据特别有用。
- 应用场景:readBytes()和writeBytes()的组合使用,使得在处理如字符串等长度可变的数据时,能够更加方便和准确。