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