Qt 文件操作 #
文件操作类概览 #
text
┌─────────────────────────────────────────────────────────────┐
│ Qt 文件操作类 │
├─────────────────────────────────────────────────────────────┤
│ │
│ QFile │
│ ├── 文件读写操作 │
│ ├── 支持文本和二进制模式 │
│ └── 继承自 QIODevice │
│ │
│ QFileInfo │
│ ├── 获取文件信息 │
│ ├── 文件名、大小、时间等 │
│ └── 不直接操作文件 │
│ │
│ QDir │
│ ├── 目录操作 │
│ ├── 遍历目录内容 │
│ └── 路径操作 │
│ │
│ QFileDialog │
│ ├── 文件选择对话框 │
│ └── 保存/打开文件 │
│ │
└─────────────────────────────────────────────────────────────┘
QFile 文件读写 #
基本读写 #
cpp
// 写入文件
void writeFile(const QString &fileName, const QString &content)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "Cannot open file for writing:" << file.errorString();
return;
}
QTextStream out(&file);
out << content;
file.close();
}
// 读取文件
QString readFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Cannot open file for reading:" << file.errorString();
return QString();
}
QTextStream in(&file);
QString content = in.readAll();
file.close();
return content;
}
使用 RAII 模式 #
cpp
// 推荐方式:使用 RAII
void writeWithRAII(const QString &fileName, const QString &content)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
// 文件会在作用域结束时自动关闭
QTextStream out(&file);
out << content;
}
逐行读取 #
cpp
void readLineByLine(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
qDebug() << line;
}
}
二进制文件操作 #
cpp
// 写入二进制数据
void writeBinary(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
return;
}
QDataStream out(&file);
out << QString("Hello");
out << 42;
out << 3.14;
out << QList<int>{1, 2, 3, 4, 5};
}
// 读取二进制数据
void readBinary(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
return;
}
QDataStream in(&file);
QString str;
int num;
double d;
QList<int> list;
in >> str >> num >> d >> list;
qDebug() << str << num << d << list;
}
文件操作标志 #
cpp
// 打开模式
QIODevice::ReadOnly // 只读
QIODevice::WriteOnly // 只写
QIODevice::ReadWrite // 读写
QIODevice::Append // 追加
QIODevice::Truncate // 清空文件
QIODevice::Text // 文本模式(转换换行符)
QIODevice::Unbuffered // 无缓冲
// 组合使用
file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
检查和错误处理 #
cpp
QFile file("test.txt");
// 检查文件是否存在
if (!file.exists()) {
qDebug() << "File does not exist";
}
// 打开文件
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Open failed:" << file.errorString();
qDebug() << "Error code:" << file.error();
return;
}
// 检查文件状态
qDebug() << "Size:" << file.size();
qDebug() << "Position:" << file.pos();
qDebug() << "At end:" << file.atEnd();
// 移动文件指针
file.seek(0); // 移动到开头
file.seek(100); // 移动到指定位置
// 刷新缓冲区
file.flush();
// 获取文件句柄
int handle = file.handle();
QFileInfo 文件信息 #
获取文件信息 #
cpp
QFileInfo info("/path/to/file.txt");
// 文件名相关
QString fileName = info.fileName(); // "file.txt"
QString baseName = info.baseName(); // "file"
QString completeBaseName = info.completeBaseName(); // "file"
QString suffix = info.suffix(); // "txt"
QString completeSuffix = info.completeSuffix(); // "txt"
QString filePath = info.filePath(); // "/path/to/file.txt"
QString absoluteFilePath = info.absoluteFilePath();
QString canonicalFilePath = info.canonicalFilePath();
// 路径相关
QString path = info.path(); // "/path/to"
QString absolutePath = info.absolutePath();
QString canonicalPath = info.canonicalPath();
// 文件属性
bool exists = info.exists();
bool isFile = info.isFile();
bool isDir = info.isDir();
bool isSymLink = info.isSymLink();
bool isReadable = info.isReadable();
bool isWritable = info.isWritable();
bool isExecutable = info.isExecutable();
bool isHidden = info.isHidden();
// 文件大小和时间
qint64 size = info.size();
QDateTime created = info.birthTime();
QDateTime modified = info.lastModified();
QDateTime read = info.lastRead();
// 符号链接
if (info.isSymLink()) {
QString target = info.symLinkTarget();
}
批量获取文件信息 #
cpp
void listFileInfo(const QString &path)
{
QDir dir(path);
QFileInfoList list = dir.entryInfoList();
for (const QFileInfo &info : list) {
qDebug() << "Name:" << info.fileName()
<< "Size:" << info.size()
<< "IsDir:" << info.isDir()
<< "Modified:" << info.lastModified();
}
}
QDir 目录操作 #
目录遍历 #
cpp
void listDirectory(const QString &path)
{
QDir dir(path);
// 获取所有条目
QStringList entries = dir.entryList();
for (const QString &entry : entries) {
qDebug() << entry;
}
// 获取详细信息列表
QFileInfoList infoList = dir.entryInfoList();
for (const QFileInfo &info : infoList) {
qDebug() << info.fileName() << info.size();
}
// 过滤条目
QStringList filters;
filters << "*.txt" << "*.cpp";
QStringList filtered = dir.entryList(filters, QDir::Files);
// 排序
QStringList sorted = dir.entryList(filters, QDir::Files, QDir::Name | QDir::Reversed);
}
目录操作 #
cpp
QDir dir;
// 创建目录
dir.mkdir("newDir");
dir.mkpath("path/to/new/dir"); // 创建多级目录
// 删除目录
dir.rmdir("emptyDir"); // 只能删除空目录
dir.rmpath("path/to/empty/dir");
// 检查目录是否存在
if (dir.exists("myDir")) {
qDebug() << "Directory exists";
}
// 切换目录
dir.cd("subDir");
dir.cdUp(); // 返回上级目录
dir.cd("/absolute/path");
// 获取当前路径
QString current = QDir::currentPath();
QString home = QDir::homePath();
QString temp = QDir::tempPath();
QString root = QDir::rootPath();
// 设置当前目录
QDir::setCurrent("/new/path");
路径操作 #
cpp
// 路径拼接
QString path = QDir::cleanPath("/path/to/../file.txt"); // "/path/file.txt"
// 绝对路径和相对路径转换
QString absolute = QDir::cleanPath(QDir::currentPath() + "/relative/path");
QString relative = QDir::current().relativeFilePath("/absolute/path");
// 路径分隔符
QString nativePath = QDir::toNativeSeparators("/path/to/file"); // Windows: "\path\to\file"
QString uniformPath = QDir::fromNativeSeparators("\\path\\to\\file"); // "/path/to/file"
// 路径组件
QString path = "/home/user/documents/file.txt";
QFileInfo info(path);
QString dirName = info.path(); // "/home/user/documents"
QString fileName = info.fileName(); // "file.txt"
QFileDialog 文件对话框 #
打开文件 #
cpp
// 选择单个文件
QString fileName = QFileDialog::getOpenFileName(
this, // 父窗口
tr("Open File"), // 标题
QDir::homePath(), // 起始目录
tr("Text Files (*.txt);;All Files (*)") // 过滤器
);
if (!fileName.isEmpty()) {
qDebug() << "Selected file:" << fileName;
}
// 选择多个文件
QStringList fileNames = QFileDialog::getOpenFileNames(
this,
tr("Open Files"),
QDir::homePath(),
tr("Images (*.png *.jpg);;All Files (*)")
);
// 选择目录
QString dirName = QFileDialog::getExistingDirectory(
this,
tr("Select Directory"),
QDir::homePath(),
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
);
保存文件 #
cpp
QString fileName = QFileDialog::getSaveFileName(
this,
tr("Save File"),
QDir::homePath() + "/untitled.txt",
tr("Text Files (*.txt);;All Files (*)")
);
if (!fileName.isEmpty()) {
// 保存文件
QFile file(fileName);
if (file.open(QIODevice::WriteOnly)) {
// 写入内容
}
}
自定义文件对话框 #
cpp
QFileDialog dialog(this);
dialog.setWindowTitle(tr("Open File"));
dialog.setDirectory(QDir::homePath());
dialog.setNameFilter(tr("Images (*.png *.jpg *.bmp)"));
dialog.setFileMode(QFileDialog::ExistingFiles); // 可选择多个文件
dialog.setViewMode(QFileDialog::Detail); // 详细视图
if (dialog.exec()) {
QStringList fileNames = dialog.selectedFiles();
for (const QString &fileName : fileNames) {
qDebug() << fileName;
}
}
文件监控 #
QFileSystemWatcher #
cpp
class FileWatcher : public QObject
{
Q_OBJECT
public:
FileWatcher(QObject *parent = nullptr) : QObject(parent)
{
watcher = new QFileSystemWatcher(this);
connect(watcher, &QFileSystemWatcher::fileChanged,
this, &FileWatcher::onFileChanged);
connect(watcher, &QFileSystemWatcher::directoryChanged,
this, &FileWatcher::onDirectoryChanged);
// 添加监控
watcher->addPath("/path/to/file.txt");
watcher->addPath("/path/to/directory");
}
private slots:
void onFileChanged(const QString &path) {
qDebug() << "File changed:" << path;
}
void onDirectoryChanged(const QString &path) {
qDebug() << "Directory changed:" << path;
}
private:
QFileSystemWatcher *watcher;
};
实用示例 #
复制文件 #
cpp
bool copyFile(const QString &source, const QString &destination)
{
if (!QFile::exists(source)) {
return false;
}
// 使用 QFile::copy
return QFile::copy(source, destination);
// 或手动复制(更多控制)
QFile srcFile(source);
QFile dstFile(destination);
if (!srcFile.open(QIODevice::ReadOnly) ||
!dstFile.open(QIODevice::WriteOnly)) {
return false;
}
dstFile.write(srcFile.readAll());
return true;
}
移动/重命名文件 #
cpp
// 重命名
QFile::rename("oldName.txt", "newName.txt");
// 移动
QFile::rename("/path/old/file.txt", "/new/path/file.txt");
删除文件 #
cpp
// 删除文件
bool removed = QFile::remove("file.txt");
// 移到回收站(Qt 5.15+)
bool moved = QFile::moveToTrash("file.txt");
下一步 #
现在你已经掌握了文件操作,接下来学习 数据流,了解 Qt 的数据序列化机制!
最后更新:2026-03-29