Qt 数据流 #
数据流概述 #
text
┌─────────────────────────────────────────────────────────────┐
│ Qt 数据流类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ QDataStream │
│ ├── 二进制数据流 │
│ ├── 跨平台二进制格式 │
│ ├── 支持多种数据类型 │
│ └── 适合文件存储和网络传输 │
│ │
│ QTextStream │
│ ├── 文本数据流 │
│ ├── 支持编码转换 │
│ ├── 方便的文本格式化 │
│ └── 适合文本文件处理 │
│ │
└─────────────────────────────────────────────────────────────┘
QDataStream 二进制数据流 #
基本使用 #
cpp
// 写入数据
void writeData(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
return;
}
QDataStream out(&file);
// 设置版本(确保跨版本兼容)
out.setVersion(QDataStream::Qt_6_0);
// 写入基本类型
out << 42; // int
out << 3.14; // double
out << true; // bool
out << QString("Hello"); // QString
out << QByteArray("data"); // QByteArray
// 写入容器
out << QList<int>{1, 2, 3};
out << QMap<QString, int>{{"one", 1}, {"two", 2}};
}
// 读取数据
void readData(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
return;
}
QDataStream in(&file);
in.setVersion(QDataStream::Qt_6_0);
// 按写入顺序读取
int num;
double d;
bool b;
QString str;
QByteArray data;
in >> num >> d >> b >> str >> data;
qDebug() << num << d << b << str << data;
}
支持的数据类型 #
cpp
QDataStream out(&file);
// 基本类型
out << qint8(1); // 8位有符号整数
out << quint8(1); // 8位无符号整数
out << qint16(1); // 16位有符号整数
out << quint16(1); // 16位无符号整数
out << qint32(1); // 32位有符号整数
out << quint32(1); // 32位无符号整数
out << qint64(1); // 64位有符号整数
out << quint64(1); // 64位无符号整数
out << float(1.0); // 单精度浮点
out << double(1.0); // 双精度浮点
out << true; // 布尔值
// Qt 类型
out << QString("text"); // 字符串
out << QByteArray("data"); // 字节数组
out << QDate::currentDate();
out << QTime::currentTime();
out << QDateTime::currentDateTime();
out << QPoint(10, 20);
out << QPointF(10.5, 20.5);
out << QSize(100, 200);
out << QRect(0, 0, 100, 200);
out << QVariant(42);
// 容器类型
out << QList<int>{1, 2, 3};
out << QStringList{"a", "b", "c"};
out << QSet<int>{1, 2, 3};
out << QMap<QString, int>{{"a", 1}};
out << QHash<QString, int>{{"a", 1}};
序列化自定义类型 #
cpp
// 自定义类型
struct Person
{
QString name;
int age;
QString email;
};
// 声明为 QDataStream 可序列化类型
QDataStream &operator<<(QDataStream &out, const Person &person)
{
out << person.name << person.age << person.email;
return out;
}
QDataStream &operator>>(QDataStream &in, Person &person)
{
in >> person.name >> person.age >> person.email;
return in;
}
// 使用
void savePerson(const QString &fileName, const Person &person)
{
QFile file(fileName);
if (file.open(QIODevice::WriteOnly)) {
QDataStream out(&file);
out << person;
}
}
Person loadPerson(const QString &fileName)
{
Person person;
QFile file(fileName);
if (file.open(QIODevice::ReadOnly)) {
QDataStream in(&file);
in >> person;
}
return person;
}
版本兼容性 #
cpp
// 设置数据流版本
QDataStream out(&file);
out.setVersion(QDataStream::Qt_6_0); // 使用 Qt 6.0 格式
// 可用版本
QDataStream::Qt_4_0
QDataStream::Qt_4_1
QDataStream::Qt_4_2
// ...
QDataStream::Qt_6_0
QDataStream::Qt_6_1
// ...
// 读取时必须使用相同版本
QDataStream in(&file);
in.setVersion(QDataStream::Qt_6_0);
字节序和浮点精度 #
cpp
QDataStream out(&file);
// 设置字节序
out.setByteOrder(QDataStream::BigEndian); // 大端
out.setByteOrder(QDataStream::LittleEndian); // 小端
// 设置浮点精度
out.setFloatingPointPrecision(QDataStream::SinglePrecision); // 32位
out.setFloatingPointPrecision(QDataStream::DoublePrecision); // 64位
状态检查 #
cpp
QDataStream in(&file);
while (!in.atEnd()) {
int value;
in >> value;
if (in.status() != QDataStream::Ok) {
qDebug() << "Error reading data";
break;
}
qDebug() << value;
}
// 重置状态
in.resetStatus();
QTextStream 文本数据流 #
基本使用 #
cpp
// 写入文本
void writeText(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
QTextStream out(&file);
// 设置编码
out.setEncoding(QStringConverter::Utf8);
// 写入文本
out << "Hello, Qt!" << Qt::endl;
out << "Line 2" << Qt::endl;
out << 42 << " " << 3.14 << Qt::endl;
// 格式化输出
out << QString("Name: %1, Age: %2").arg("Alice").arg(25) << Qt::endl;
}
// 读取文本
void readText(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
QTextStream in(&file);
in.setEncoding(QStringConverter::Utf8);
// 读取全部
QString all = in.readAll();
qDebug() << all;
// 或逐行读取
in.seek(0); // 回到开头
while (!in.atEnd()) {
QString line = in.readLine();
qDebug() << line;
}
}
编码设置 #
cpp
QTextStream stream(&file);
// 设置编码
stream.setEncoding(QStringConverter::Utf8);
stream.setEncoding(QStringConverter::Latin1);
stream.setEncoding(QStringConverter::Local8Bit); // 系统本地编码
// 自动检测编码
stream.setAutoDetectUnicode(true);
字段格式化 #
cpp
QTextStream out(&file);
// 设置字段宽度
out.setFieldWidth(10);
out << "Name" << "Age" << "City" << Qt::endl;
out << "Alice" << 25 << "Beijing" << Qt::endl;
// 设置对齐方式
out.setFieldAlignment(QTextStream::AlignLeft);
out << "Left" << Qt::endl;
out.setFieldAlignment(QTextStream::AlignRight);
out << "Right" << Qt::endl;
out.setFieldAlignment(QTextStream::AlignCenter);
out << "Center" << Qt::endl;
// 设置填充字符
out.setPadChar('-');
out << "Padded" << Qt::endl;
数字格式化 #
cpp
QTextStream out(&file);
// 整数进制
out.setIntegerBase(10); // 十进制
out << 42 << Qt::endl;
out.setIntegerBase(16); // 十六进制
out << 42 << Qt::endl; // 输出 "2a"
out.setIntegerBase(2); // 二进制
out << 42 << Qt::endl; // 输出 "101010"
// 实数格式
out.setRealNumberNotation(QTextStream::ScientificNotation);
out << 3.14159 << Qt::endl; // 科学计数法
out.setRealNumberNotation(QTextStream::FixedNotation);
out << 3.14159 << Qt::endl; // 固定小数点
out.setRealNumberPrecision(2); // 小数位数
out << 3.14159 << Qt::endl; // 输出 "3.14"
读取操作 #
cpp
QTextStream in(&file);
// 读取所有
QString all = in.readAll();
// 读取一行
QString line = in.readLine();
// 读取指定字符数
QString chunk = in.read(100);
// 读取到分隔符
QString word;
while (!in.atEnd()) {
in >> word; // 按空白分隔读取
qDebug() << word;
}
// 读取单个字符
QChar ch;
in >> ch;
实用示例 #
配置文件读写 #
cpp
class Config : public QObject
{
Q_OBJECT
public:
void save(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
return;
}
QDataStream out(&file);
out.setVersion(QDataStream::Qt_6_0);
// 写入魔数和版本
out << quint32(0x12345678);
out << quint32(1); // 版本号
// 写入配置数据
out << m_settings;
}
bool load(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
return false;
}
QDataStream in(&file);
in.setVersion(QDataStream::Qt_6_0);
// 验证魔数和版本
quint32 magic, version;
in >> magic >> version;
if (magic != 0x12345678) {
return false;
}
// 读取配置数据
in >> m_settings;
return true;
}
private:
QMap<QString, QVariant> m_settings;
};
CSV 文件处理 #
cpp
void writeCsv(const QString &fileName, const QList<QStringList> &data)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
QTextStream out(&file);
out.setEncoding(QStringConverter::Utf8);
for (const QStringList &row : data) {
QStringList escapedRow;
for (const QString &cell : row) {
// 处理包含逗号或引号的字段
QString escaped = cell;
if (escaped.contains(',') || escaped.contains('"')) {
escaped.replace('"', "\"\"");
escaped = '"' + escaped + '"';
}
escapedRow << escaped;
}
out << escapedRow.join(',') << Qt::endl;
}
}
QList<QStringList> readCsv(const QString &fileName)
{
QList<QStringList> data;
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return data;
}
QTextStream in(&file);
in.setEncoding(QStringConverter::Utf8);
while (!in.atEnd()) {
QString line = in.readLine();
// 简单解析(实际应使用更完善的 CSV 解析器)
data << line.split(',');
}
return data;
}
下一步 #
现在你已经掌握了数据流的使用,接下来学习 多线程,了解 Qt 的多线程编程!
最后更新:2026-03-29