Qt5 文件与数据处理详解
个人博客:blogs.wurp.top
一、文件操作基础
Qt5 使用 QFile
类进行基本的文件操作,它继承自 QIODevice
,提供了读写文件的接口。
#include <QFile>
#include <QDebug>void basicFileOperations() {// 创建 QFile 对象QFile file("example.txt");// 检查文件是否存在if (file.exists()) {qDebug() << "File exists";} else {qDebug() << "File does not exist";}// 打开文件进行写入if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {file.write("Hello, Qt5!");file.close(); // 记得关闭文件}// 打开文件进行读取if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {QByteArray data = file.readAll();qDebug() << "File content:" << data;file.close();}// 删除文件if (file.remove()) {qDebug() << "File removed successfully";} else {qDebug() << "Failed to remove file:" << file.errorString();}
}
二、文本文件处理
对于文本文件,Qt 提供了 QTextStream
类,它可以自动处理编码和换行符。
#include <QFile>
#include <QTextStream>
#include <QDebug>void textFileOperations() {QFile file("textfile.txt");// 写入文本文件if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {QTextStream out(&file);out.setCodec("UTF-8"); // 设置编码out << "Line 1: Hello Qt5!\n";out << "Line 2: 这是第二行\n";out << "Line 3: Number: " << 42 << "\n";file.close();}// 读取文本文件if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {QTextStream in(&file);in.setCodec("UTF-8");QString line;while (!in.atEnd()) {line = in.readLine();qDebug() << "Read line:" << line;}file.close();}
}
三、二进制文件处理
对于二进制文件,可以使用 QDataStream
类,它提供了类型安全的二进制数据读写。
#include <QFile>
#include <QDataStream>
#include <QDebug>void binaryFileOperations() {QFile file("binary.dat");// 写入二进制数据if (file.open(QIODevice::WriteOnly)) {QDataStream out(&file);out.setVersion(QDataStream::Qt_5_15); // 设置版本以确保兼容性// 写入各种类型的数据out << QString("Hello Binary");out << qint32(42);out << 3.14159;out << QByteArray("Raw data");file.close();}// 读取二进制数据if (file.open(QIODevice::ReadOnly)) {QDataStream in(&file);in.setVersion(QDataStream::Qt_5_15);QString text;qint32 number;double pi;QByteArray data;// 读取顺序必须与写入顺序一致in >> text >> number >> pi >> data;qDebug() << "Text:" << text;qDebug() << "Number:" << number;qDebug() << "Pi:" << pi;qDebug() << "Data:" << data;file.close();}
}
四、目录操作
Qt 提供了 QDir
类来处理目录操作。
#include <QDir>
#include <QFileInfo>
#include <QDebug>void directoryOperations() {// 创建 QDir 对象QDir dir;// 获取当前目录qDebug() << "Current directory:" << dir.currentPath();// 创建目录if (!dir.exists("test_dir")) {if (dir.mkdir("test_dir")) {qDebug() << "Directory created successfully";} else {qDebug() << "Failed to create directory";}}// 列出目录内容dir.setPath("."); // 设置为当前目录QFileInfoList list = dir.entryInfoList();for (const QFileInfo &info : list) {qDebug() << (info.isDir() ? "[DIR] " : "[FILE]") << info.fileName();}// 删除目录if (dir.exists("test_dir")) {if (dir.rmdir("test_dir")) {qDebug() << "Directory removed successfully";} else {qDebug() << "Failed to remove directory";}}
}
五、文件信息获取
使用 QFileInfo
类可以获取文件的详细信息。
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>void fileInfoOperations() {QFileInfo info("example.txt");if (info.exists()) {qDebug() << "File name:" << info.fileName();qDebug() << "Absolute path:" << info.absoluteFilePath();qDebug() << "Size:" << info.size() << "bytes";qDebug() << "Created:" << info.birthTime().toString();qDebug() << "Last modified:" << info.lastModified().toString();qDebug() << "Is readable?" << info.isReadable();qDebug() << "Is writable?" << info.isWritable();qDebug() << "Is executable?" << info.isExecutable();} else {qDebug() << "File does not exist";}
}
六、数据序列化与持久化
Qt 提供了强大的数据序列化功能,可以将复杂的数据结构保存到文件中。
基本序列化
#include <QDataStream>
#include <QFile>
#include <QMap>
#include <QList>
#include <QDebug>void dataSerialization() {// 创建一些复杂数据QMap<QString, QVariant> data;data["name"] = "John Doe";data["age"] = 30;data["scores"] = QList<int>{95, 88, 92};QList<QString> hobbies = {"Reading", "Swimming", "Coding"};data["hobbies"] = QVariant::fromValue(hobbies);// 序列化到文件QFile file("data.bin");if (file.open(QIODevice::WriteOnly)) {QDataStream out(&file);out.setVersion(QDataStream::Qt_5_15);out << data;file.close();}// 从文件反序列化QMap<QString, QVariant> loadedData;if (file.open(QIODevice::ReadOnly)) {QDataStream in(&file);in.setVersion(QDataStream::Qt_5_15);in >> loadedData;file.close();qDebug() << "Loaded data:" << loadedData;}
}
自定义对象的序列化
#include <QDataStream>
#include <QFile>
#include <QDebug>// 自定义类
class Person {
public:Person() : age(0) {}Person(const QString &name, int age) : name(name), age(age) {}// 重载操作符以实现序列化friend QDataStream &operator<<(QDataStream &out, const Person &person) {out << person.name << person.age;return out;}// 重载操作符以实现反序列化friend QDataStream &operator>>(QDataStream &in, Person &person) {in >> person.name >> person.age;return in;}QString toString() const {return QString("Person{name: %1, age: %2}").arg(name).arg(age);}private:QString name;int age;
};void customObjectSerialization() {Person person("Alice", 25);// 序列化到文件QFile file("person.bin");if (file.open(QIODevice::WriteOnly)) {QDataStream out(&file);out.setVersion(QDataStream::Qt_5_15);out << person;file.close();}// 从文件反序列化Person loadedPerson;if (file.open(QIODevice::ReadOnly)) {QDataStream in(&file);in.setVersion(QDataStream::Qt_5_15);in >> loadedPerson;file.close();qDebug() << "Loaded person:" << loadedPerson.toString();}
}
七、高级文件操作
使用 QSaveFile 安全保存
QSaveFile
提供了原子性写操作,确保在写入过程中发生错误时不会损坏原有文件。
#include <QSaveFile>
#include <QTextStream>
#include <QDebug>void safeFileWrite() {QSaveFile file("important.txt");if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {QTextStream out(&file);out << "This is important data that must not be corrupted!\n";out << "More important data...\n";// 只有调用 commit() 后,更改才会生效if (file.commit()) {qDebug() << "File saved successfully";} else {qDebug() << "Failed to save file:" << file.errorString();}}
}
文件监视
#include <QFileSystemWatcher>
#include <QDebug>void fileMonitoring() {QFileSystemWatcher *watcher = new QFileSystemWatcher();// 添加要监视的文件和目录watcher->addPath("monitored.txt");watcher->addPath("."); // 当前目录// 连接信号和槽QObject::connect(watcher, &QFileSystemWatcher::fileChanged, [](const QString &path) {qDebug() << "File changed:" << path;});QObject::connect(watcher, &QFileSystemWatcher::directoryChanged, [](const QString &path) {qDebug() << "Directory changed:" << path;});// 注意:watcher 对象需要保持生命周期// 在实际应用中,通常将其作为类的成员变量
}
临时文件
#include <QTemporaryFile>
#include <QTextStream>
#include <QDebug>void temporaryFileExample() {// 创建临时文件QTemporaryFile tempFile;if (tempFile.open()) {QTextStream out(&tempFile);out << "This is temporary data\n";out << "It will be automatically deleted when the file is closed\n";qDebug() << "Temporary file created:" << tempFile.fileName();// 临时文件会在对象销毁时自动删除// 如果需要立即关闭并删除,可以调用 close()tempFile.close();}
}
八、完整示例
下面是一个完整的示例,演示了多种文件操作功能:
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
#include <QDataStream>
#include <QDir>
#include <QFileInfo>
#include <QSaveFile>
#include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 1. 基本文件操作qDebug() << "=== Basic File Operations ===";QFile basicFile("basic.txt");if (basicFile.open(QIODevice::WriteOnly | QIODevice::Text)) {basicFile.write("Hello, basic file operations!");basicFile.close();}// 2. 文本文件操作qDebug() << "\n=== Text File Operations ===";QFile textFile("text.txt");if (textFile.open(QIODevice::WriteOnly | QIODevice::Text)) {QTextStream textOut(&textFile);textOut << "Line 1: Hello Text Stream!\n";textOut << "Line 2: 这是第二行文本\n";textOut << "Line 3: Number: " << 123 << "\n";textFile.close();}// 3. 二进制文件操作qDebug() << "\n=== Binary File Operations ===";QFile binaryFile("binary.bin");if (binaryFile.open(QIODevice::WriteOnly)) {QDataStream binaryOut(&binaryFile);binaryOut.setVersion(QDataStream::Qt_5_15);binaryOut << QString("Binary data");binaryOut << qint32(456);binaryOut << 2.71828;binaryFile.close();}// 4. 目录操作qDebug() << "\n=== Directory Operations ===";QDir dir;if (!dir.exists("test_dir")) {dir.mkdir("test_dir");qDebug() << "Created directory: test_dir";}// 5. 文件信息qDebug() << "\n=== File Information ===";QFileInfo fileInfo("text.txt");if (fileInfo.exists()) {qDebug() << "File name:" << fileInfo.fileName();qDebug() << "File size:" << fileInfo.size() << "bytes";qDebug() << "Last modified:" << fileInfo.lastModified().toString();}// 6. 安全文件写入qDebug() << "\n=== Safe File Write ===";QSaveFile saveFile("safe.txt");if (saveFile.open(QIODevice::WriteOnly | QIODevice::Text)) {QTextStream saveOut(&saveFile);saveOut << "This data is safely written!\n";if (saveFile.commit()) {qDebug() << "File saved safely";}}// 7. 清理:删除创建的文件和目录qDebug() << "\n=== Cleanup ===";QFile::remove("basic.txt");QFile::remove("text.txt");QFile::remove("binary.bin");QFile::remove("safe.txt");if (dir.exists("test_dir")) {dir.rmdir("test_dir");qDebug() << "Removed directory: test_dir";}qDebug() << "\nAll operations completed!";return 0;
}
九、总结
Qt5 提供了全面的文件操作和数据处理功能:
- 基本文件操作 - 使用
QFile
进行文件的创建、读写和删除 - 文本文件处理 - 使用
QTextStream
处理文本数据,支持编码转换 - 二进制文件处理 - 使用
QDataStream
进行类型安全的二进制数据读写 - 目录操作 - 使用
QDir
进行目录的创建、遍历和删除 - 文件信息获取 - 使用
QFileInfo
获取文件的详细信息 - 数据序列化 - 使用
QDataStream
序列化复杂数据结构和自定义对象 - 高级文件操作 - 使用
QSaveFile
进行安全写入,QFileSystemWatcher
进行文件监视,QTemporaryFile
处理临时文件