Qt 二進制數據讀寫詳解
一、Qt 二進制數據讀寫講解
1、核心概念
- QByteArray:這是 Qt 中處理原始字節(jié)數據的核心容器類。它可以存儲任意字節(jié)序列(char* 數據)。
- QFile:用于訪問文件系統(tǒng)中的文件。它可以以文本模式或二進制模式打開文件。
- QDataStream:提供了一種序列化的方式,將基本數據類型(如 int, float, QString 等)和更復雜的結構轉換成字節(jié)流,以便寫入文件或網絡套接字,并能從字節(jié)流中還原出來。它負責處理字節(jié)序(Endianness)等問題。
- QBuffer:將 QByteArray 當作一個 QIODevice(類似于文件或套接字)來使用,方便進行流式操作。
2、二進制寫入操作
2.1、方法一:直接使用QFile和QByteArray
#include <QFile>
#include <QByteArray>
// 準備要寫入的二進制數據
QByteArray data;
data.append(0x01); // 寫入一個字節(jié) 0x01
data.append(0x02); // 寫入一個字節(jié) 0x02
// ... 可以填充任意字節(jié)
// 打開文件 (使用 QIODevice::WriteOnly 和 QIODevice::Truncate 確保清空原有內容)
QFile file("binary.dat");
if (file.open(QIODevice::WriteOnly)) {
// 將整個 QByteArray 寫入文件
qint64 bytesWritten = file.write(data);
if (bytesWritten == -1) {
// 處理寫入錯誤
}
file.close(); // 關閉文件
} else {
// 處理文件打開失敗
}
2.2、方法二:使用QDataStream進行序列化(推薦)
#include <QFile>
#include <QDataStream>
QFile file("structured.dat");
if (file.open(QIODevice::WriteOnly)) {
QDataStream out(&file);
out.setVersion(QDataStream::Qt_6_5); // 設置序列化版本,保證兼容性
// 寫入各種類型的數據
quint8 byteValue = 0xAB;
qint32 intValue = 123456;
float floatValue = 3.14159f;
QString stringValue = "Hello Binary";
out << byteValue; // 寫入一個字節(jié) (quint8)
out << intValue; // 寫入一個 32 位整數
out << floatValue; // 寫入一個浮點數
out << stringValue; // 寫入一個字符串 (Qt 會處理其內部編碼和長度)
file.close();
} else {
// 處理錯誤
}
QDataStream 會自動處理不同平臺上可能存在的字節(jié)序問題(大端序 Big-Endian 或小端序 Little-Endian)。默認情況下,它使用大端序。你也可以使用 out.setByteOrder(QDataStream::LittleEndian) 顯式設置。
3、二進制讀取操作
3.1、方法一:直接使用QFile和QByteArray
#include <QFile>
#include <QByteArray>
QFile file("binary.dat");
if (file.open(QIODevice::ReadOnly)) {
// 一次性讀取整個文件內容到 QByteArray
QByteArray allData = file.readAll();
file.close();
// 處理 allData
if (allData.size() >= 2) {
quint8 firstByte = static_cast<quint8>(allData.at(0)); // 讀取第一個字節(jié)
quint8 secondByte = static_cast<quint8>(allData.at(1)); // 讀取第二個字節(jié)
// ... 根據協議解析后續(xù)字節(jié)
}
} else {
// 處理錯誤
}
3.2、方法二:使用QDataStream進行反序列化(推薦)
#include <QFile>
#include <QDataStream>
QFile file("structured.dat");
if (file.open(QIODevice::ReadOnly)) {
QDataStream in(&file);
in.setVersion(QDataStream::Qt_6_5); // 必須與寫入時使用的版本一致!
// 按寫入順序讀取數據
quint8 byteValue;
qint32 intValue;
float floatValue;
QString stringValue;
in >> byteValue; // 讀取一個字節(jié)
in >> intValue; // 讀取一個 32 位整數
in >> floatValue; // 讀取浮點數
in >> stringValue; // 讀取字符串
file.close();
// 現在可以使用讀取到的數據 byteValue, intValue, floatValue, stringValue
} else {
// 處理錯誤
}
使用 QDataStream 讀取時,順序和類型必須與寫入時完全一致,否則會導致數據錯亂或讀取失敗。QDataStream 會維護一個狀態(tài),你可以通過 in.status() 檢查是否有錯誤發(fā)生。
4、使用QBuffer進行內存讀寫
#include <QBuffer>
#include <QDataStream>
QByteArray bufferData; // 最終數據將存儲在這里
QBuffer buffer(&bufferData);
buffer.open(QIODevice::WriteOnly); // 打開 Buffer 用于寫入
QDataStream out(&buffer);
out << QString("Data in Memory") << 42;
buffer.close(); // 此時 bufferData 包含了序列化后的數據
// 從 bufferData 讀取
buffer.setBuffer(&bufferData); // 關聯同一個 QByteArray
buffer.open(QIODevice::ReadOnly); // 打開 Buffer 用于讀取
QDataStream in(&buffer);
QString str;
int num;
in >> str >> num;
buffer.close();
5、注意事項
- 字節(jié)序:如果數據需要在不同架構(x86, ARM 等)或不同系統(tǒng)(Windows, Linux, macOS)間交換,務必使用
QDataStream并統(tǒng)一設置字節(jié)序(通常用默認的大端序或顯式設置)。 - 版本控制:
QDataStream的序列化格式在不同 Qt 版本間可能有微小變化。使用setVersion指定一致的版本號(如Qt_6_5)可以保證長期存儲或跨版本程序的數據兼容性。 - 錯誤處理:始終檢查文件是否成功打開、讀寫操作是否成功(
write返回寫入字節(jié)數,QDataStream::status())。 - 類型匹配:讀取時使用的類型必須與寫入時完全匹配(例如,寫入
qint32就必須讀取qint32,不能是int,除非你確定平臺上的int就是 32 位)。 - 性能:對于大文件,考慮分塊讀取寫入,避免一次性
readAll()消耗過多內存。 - 安全性:讀取外部二進制文件時要注意潛在的安全風險(如緩沖區(qū)溢出)。
6、示例:一個簡單的十六進制查看器片段
#include <QFile>
#include <QDebug>
void viewHex(const QString &filename) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Failed to open file";
return;
}
QByteArray data = file.read(16); // 每次讀取 16 字節(jié)
while (!data.isEmpty()) {
qDebug().noquote() << data.toHex(' ').toUpper(); // 轉換為十六進制字符串,空格分隔,大寫
data = file.read(16);
}
file.close();
}
二、示例
1、源碼
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QDataStream>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_write_clicked()
{
// 二進制數據寫入
qDebug()<<"開始寫入!";
QFile writeFile("data.bin");
if (!writeFile.open(QIODevice::WriteOnly)) {
qDebug() << "文件打開失敗";
return ;
}
QDataStream outStream(&writeFile);
outStream.setVersion(QDataStream::Qt_6_0); // 設置數據流版本
int intValue = 42;
double doubleValue = 3.14159;
QString stringValue = "Qt二進制示例";
// 寫入不同類型數據
outStream << intValue << doubleValue << stringValue;
writeFile.close();
qDebug()<<"寫入成功!";
}
void MainWindow::on_read_clicked()
{
// 二進制數據讀取
qDebug()<<"開始讀??!";
QFile readFile("data.bin");
if (!readFile.open(QIODevice::ReadOnly)) {
qDebug() << "文件打開失敗";
return;
}
QDataStream inStream(&readFile);
inStream.setVersion(QDataStream::Qt_6_0);
int readInt;
double readDouble;
QString readString;
// 按寫入順序讀取數據
inStream >> readInt >> readDouble >> readString;
readFile.close();
qDebug()<<"讀取成功!";
// 驗證讀取結果
qDebug() << "讀取整數:" << readInt;
qDebug() << "讀取浮點數:" << readDouble;
qDebug() << "讀取字符串:" << readString;
}
代碼說明:
二進制寫入:
- 使用
QFile以QIODevice::WriteOnly模式創(chuàng)建文件 QDataStream提供序列化接口- 通過
<<操作符寫入多種數據類型
- 使用
二進制讀取:
- 以
QIODevice::ReadOnly模式打開文件 - 使用相同的
QDataStream版本 - 通過
>>操作符按寫入順序讀取數據
- 以
注意事項:
- 數據流版本需保持一致(
Qt_6_0可替換為實際版本) - 讀取順序必須與寫入順序嚴格一致
- 支持所有Qt基本類型和容器類(如
QList,QMap)
- 數據流版本需保持一致(
數據類型支持:
- 基本類型:
int,float,double,bool等 - Qt類型:
QString,QByteArray,QDateTime等 - 自定義類型(需實現序列化操作符)
- 基本類型:
2、運行效果


到此這篇關于Qt 二進制數據讀寫詳解的文章就介紹到這了,更多相關Qt 二進制數據讀寫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Cocos2d-x保存用戶游戲數據之XML文件是否存在問題判斷方法
這篇文章主要介紹了Cocos2d-x保存用戶游戲數據之XML文件是否存在問題判斷方法,請注意代碼中包含大量注釋,需要的朋友可以參考下2014-09-09

