Qt 文件操作:QFile 读写全解析(2026最新实用总结)
Qt 中最常用的文件操作类就是 QFile,它继承自 QIODevice,可以处理文本文件和二进制文件。
一、常用打开模式(OpenMode)
| 标志 | 含义 | 常用组合示例 |
|---|---|---|
QIODevice::ReadOnly | 只读 | 读取配置文件、日志 |
QIODevice::WriteOnly | 只写(会清空原文件) | 创建新文件、覆盖写 |
QIODevice::ReadWrite | 读+写 | 修改已有文件 |
QIODevice::Append | 追加模式(写在文件末尾) | 日志记录 |
QIODevice::Text | 文本模式(自动处理换行符) | 几乎所有文本文件都要加 |
QIODevice::Truncate | 打开时清空文件(常与WriteOnly一起) | 重新生成文件 |
QIODevice::Unbuffered | 不使用缓冲(一般不推荐) | 极少数实时写入场景 |
最常用的几种组合:
QIODevice::ReadOnly | QIODevice::Text
QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate
QIODevice::Append | QIODevice::Text
QIODevice::ReadWrite | QIODevice::Text
二、基本读写操作对比表
| 需求 | 推荐方式 | 代码关键语句 | 适用场景 |
|---|---|---|---|
| 一次性读全部文本 | QTextStream + readAll() | in.readAll() | 小~中型配置文件 |
| 按行读取文本 | QTextStream + readLine() | while(!in.atEnd()) QString line = in.readLine(); | 逐行解析日志、CSV、ini |
| 一次性读全部字节 | QFile::readAll() | file.readAll() → QByteArray | 小图片、配置文件二进制读取 |
| 按块读取(大文件) | QFile::read() | while(!file.atEnd()) ba += file.read(4096); | 几百MB以上的文件 |
| 写纯文本(推荐) | QTextStream << | out << "内容" << Qt::endl; | 写日志、配置文件、JSON等 |
| 追加写文本 | Append + QTextStream | file.open(QIODevice::Append | ...) | 日志系统 |
| 写二进制数据 | QDataStream << | QDataStream out(&file); out << quint32(0x1234) << str; | 自定义格式、序列化对象 |
| 写原始字节 | QFile::write() | file.write(ba); | 图片、音频、已编码数据 |
三、最常用/最推荐的几种写法(2025-2026主流写法)
1. 写文本文件(最常用方式)
#include <QFile>
#include <QTextStream>
#include <QDebug>
bool writeTextFile(const QString &path, const QString &content)
{
QFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
{
qWarning() << "打开失败:" << file.errorString();
return false;
}
QTextStream out(&file);
out.setCodec("UTF-8"); // 非常重要!防止中文乱码
// out.setGenerateByteOrderMark(true); // 可选:加BOM(Windows记事本友好)
out << content << "\n";
out << "第二行内容\n";
out << QString("当前时间:%1\n").arg(QDateTime::currentDateTime().toString());
file.close(); // 推荐显式关闭(虽然析构时也会关)
return true;
}
2. 读文本文件全部内容(最简洁)
QString readAllText(const QString &path)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return QString();
QTextStream in(&file);
in.setCodec("UTF-8");
QString content = in.readAll();
return content;
}
3. 按行读取 + 处理(日志/配置/CSV常用)
bool readLineByLine(const QString &path)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream in(&file);
in.setCodec("UTF-8");
while (!in.atEnd())
{
QString line = in.readLine().trimmed(); // 去掉首尾空白
if (line.isEmpty() || line.startsWith("#")) continue; // 跳过空行和注释
// 简单解析示例: key=value
int idx = line.indexOf('=');
if (idx > 0)
{
QString key = line.left(idx).trimmed();
QString val = line.mid(idx+1).trimmed();
qDebug() << key << "->" << val;
}
}
return true;
}
4. 二进制读写(图片、自定义格式)
bool copyFileBinary(const QString &src, const QString &dst)
{
QFile inFile(src);
QFile outFile(dst);
if (!inFile.open(QIODevice::ReadOnly)) return false;
if (!outFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
inFile.close();
return false;
}
// 方式1:一次性读(文件不大时推荐)
// QByteArray data = inFile.readAll();
// outFile.write(data);
// 方式2:分块读写(推荐用于大文件)
constexpr qint64 BUFFER_SIZE = 8192;
QByteArray buffer;
buffer.resize(BUFFER_SIZE);
while (!inFile.atEnd())
{
qint64 len = inFile.read(buffer.data(), BUFFER_SIZE);
if (len > 0)
outFile.write(buffer.data(), len);
}
return true;
}
四、QFile 常用实用成员函数速查
| 函数 | 作用 | 返回类型 | 备注 |
|---|---|---|---|
exists() | 文件是否存在 | bool | 静态/非静态都可 |
size() | 文件大小(字节) | qint64 | 已打开或未打开都可调用 |
fileName() / setFileName() | 获取/设置路径 | QString | — |
errorString() | 最后错误描述 | QString | 调试神器 |
permissions() | 文件权限 | QFile::Permissions | |
resize(qint64 size) | 改变文件大小(截断或扩展) | bool | 常用于预分配空间 |
remove() / rename() | 删除/重命名 | bool | 不需要先open |
copy() / moveToTrash() | 复制 / 移到回收站(Qt6+) | bool | 静态函数 |
五、写在最后(2026年最常踩的坑)
- 中文乱码 → 永远记得
setCodec("UTF-8") - Windows换行符 → 文本模式下会自动处理,但二进制模式不要加
Text标志 - 文件被占用 → Windows下常见,记得判断
open()返回值 - 超大文件 → 不要用
readAll(),改用分块读取 - 路径问题 → 推荐用
QDir::toNativeSeparators()或直接用/(Qt内部会转换)
希望这份总结能帮你快速掌握 QFile 的核心用法。
你目前最常遇到哪种文件读写场景?(日志?配置?图片?大文件?序列化?)可以告诉我,我可以给你更针对性的代码模板。