Qt中QByteArray?類型的使用詳解
在Qt開發(fā)中,QByteArray? 是處理原始字節(jié)數(shù)據(jù)(Raw Bytes)、8位字符串(如ASCII/Latin-1/UTF-8)和二進(jìn)制 payload? 的核心容器類。它類似C++的std::vector<char>或C風(fēng)格字符串,但提供了更安全、更便捷的API,且與Qt生態(tài)(如QString、網(wǎng)絡(luò)模塊、文件IO)深度集成。
一、核心定位
QByteArray的設(shè)計(jì)目標(biāo)是:
- 存儲(chǔ)無(wú)編碼的二進(jìn)制數(shù)據(jù)(如圖像像素、RTP payload、加密數(shù)據(jù));
- 處理8位編碼的字符串(如HTTP頭部的ASCII文本、RTSP協(xié)議的UTF-8 URL);
- 替代C風(fēng)格的
char[],避免手動(dòng)內(nèi)存管理和越界風(fēng)險(xiǎn)。
二、基礎(chǔ)操作:構(gòu)造與賦值
QByteArray支持多種初始化方式,覆蓋常見場(chǎng)景:
1. 空對(duì)象
QByteArray ba; // 空字節(jié)序列,size=0
2. 從C風(fēng)格字符串構(gòu)造
const char* cstr = "Hello, Qt!"; QByteArray ba(cstr); // 內(nèi)容:"Hello, Qt!"(自動(dòng)添加'\0'?不,QByteArray不強(qiáng)制以'\0'結(jié)尾,除非顯式包含)
3. 從QString轉(zhuǎn)換(編碼敏感)
需指定編碼(如UTF-8/Latin1),將Unicode字符串轉(zhuǎn)為字節(jié)序列:
QString str = "你好,Qt!"; QByteArray utf8Ba = str.toUtf8(); // UTF-8編碼的字節(jié)序列 QByteArray latin1Ba = str.toLatin1();// Latin1編碼(每個(gè)字符1字節(jié))
反向轉(zhuǎn)換(字節(jié)序列→QString):
QString fromUtf8 = QString::fromUtf8(utf8Ba); // 轉(zhuǎn)回Unicode字符串 QString fromLatin1 = QString::fromLatin1(latin1Ba);
4. 填充重復(fù)字符
QByteArray filledBa = QByteArray::fromRawData("ABCD", 4); // 從原始數(shù)據(jù)創(chuàng)建(不復(fù)制)
filledBa.fill('X', 3); // 修改為"XXXD"(size=4,前3個(gè)字符替換為'X')
// 或:QByteArray ba; ba.fill('Y', 5); // 創(chuàng)建5個(gè)'Y':"YYYYY"5. 靜態(tài)工廠方法(常用)
fromHex():將十六進(jìn)制字符串轉(zhuǎn)為字節(jié)序列
QByteArray hex = QByteArray::fromHex("48656c6c6f"); // 對(duì)應(yīng)"Hello"的字節(jié)(0x48=H, 0x65=e...)fromStdString():將std::string轉(zhuǎn)為QByteArray
std::string stdStr = "std::string"; QByteArray ba = QByteArray::fromStdString(stdStr);
三、數(shù)據(jù)訪問(wèn):讀寫與遍歷
QByteArray提供安全和高效的訪問(wèn)方式,避免越界:
1. 下標(biāo)訪問(wèn)
- at(int i):只讀,返回const char&,越界時(shí)觸發(fā)斷言(Debug模式)。
- operator[](int i):可讀寫,返回char&,Debug模式下越界檢查,Release模式未定義。
QByteArray ba("Hello");
char c1 = ba.at(1); // 'e'(只讀)
ba[0] = 'h'; // 修改為"hello"2. 原始指針訪問(wèn)
constData():返回const char*,指向內(nèi)部數(shù)據(jù)(不修改)。data():非const對(duì)象返回char*(可修改),const對(duì)象返回const char*。
?? 注意:若QByteArray修改(如append)導(dǎo)致內(nèi)存重新分配,舊指針會(huì)失效!
const char* ptr = ba.constData(); // 指向"h"
ba.append("ello"); // 內(nèi)存可能重新分配
// ptr 此時(shí)可能指向無(wú)效內(nèi)存!3. 遍歷字節(jié)
// 方式1:基于下標(biāo)
for (int i = 0; i < ba.size(); ++i) {
qDebug() << static_cast<int>(ba[i]); // 打印每個(gè)字節(jié)的整數(shù)值
}
// 方式2:迭代器(Qt風(fēng)格)
for (auto it = ba.begin(); it != ba.end(); ++it) {
qDebug() << *it;
}四、容量與內(nèi)存管理
QByteArray動(dòng)態(tài)管理內(nèi)存,支持預(yù)分配和收縮:
1. 容量查詢
size():當(dāng)前存儲(chǔ)的字節(jié)數(shù)。isEmpty():等價(jià)于size() == 0,更高效。capacity():當(dāng)前分配的內(nèi)存容量(≥size())。
2. 預(yù)分配內(nèi)存
提前預(yù)留空間,避免頻繁擴(kuò)容:
QByteArray ba;
ba.reserve(1024); // 預(yù)分配1024字節(jié),后續(xù)append無(wú)需重新分配
for (int i = 0; i < 1000; ++i) {
ba.append('a');
}3. 收縮內(nèi)存
若容量遠(yuǎn)大于實(shí)際大小,可釋放多余內(nèi)存:
ba.resize(10); // 縮小size到10 ba.squeeze(); // capacity變?yōu)?0,釋放多余內(nèi)存
4. 清空數(shù)據(jù)
ba.clear(); // size=0,capacity不變
五、修改操作:增刪改查
QByteArray提供豐富的方法處理字節(jié)序列:
1. 追加(Append)
QByteArray ba("Hello");
ba.append(" World"); // "Hello World"
ba.append('!');
ba.append(QByteArray::fromHex("00FF")); // 追加兩個(gè)十六進(jìn)制字節(jié):0x00, 0xFF2. 插入(Insert)
ba.insert(5, ", Qt"); // 在第5位插入,變成"Hello, Qt World!"
3. 刪除(Remove)
ba.remove(5, 4); // 刪除從第5位開始的4個(gè)字符(", Qt"),回到"Hello World!"
4. 替換(Replace)
ba.replace("World", "Qt"); // "Hello Qt!"
ba.replace(6, 2, "Qt"); // 從第6位替換2個(gè)字符為"Qt",同上
ba.replace('l', 'L'); // 全局替換:'Hello Qt!' → 'HeLLo Qt!'5. 子串提取
left(int n):取前n個(gè)字節(jié)。right(int n):取后n個(gè)字節(jié)。mid(int pos):從pos到末尾。mid(int pos, int len):從pos取len個(gè)字節(jié)。
QByteArray ba("Hello World");
QByteArray left = ba.left(5); // "Hello"
QByteArray mid = ba.mid(6); // "World"
QByteArray right = ba.right(6); // "World"六、查找與比較
1. 查找
contains(const QByteArray& str):是否包含子串。indexOf(const QByteArray& str):返回第一個(gè)匹配的索引(-1表示未找到)。lastIndexOf(const QByteArray& str):返回最后一個(gè)匹配的索引。startsWith(const QByteArray& prefix):是否以prefix開頭。endsWith(const QByteArray& suffix):是否以suffix結(jié)尾。
QByteArray ba("Hello World");
bool hasHello = ba.contains("Hello"); // true
int idx = ba.indexOf("World"); // 6
bool startsWithHe = ba.startsWith("He"); // true2. 比較
operator==:內(nèi)容+大小完全一致才相等。operator<:按字典序比較(字節(jié)級(jí))。equals(const QByteArray& other):等價(jià)于==。
QByteArray a("abc");
QByteArray b("abd");
bool equal = (a == b); // false
bool less = (a < b); // true七、編碼與轉(zhuǎn)換
QByteArray常用來(lái)處理編碼轉(zhuǎn)換,尤其是與網(wǎng)絡(luò)協(xié)議、文件格式交互時(shí):
1. 轉(zhuǎn)為十六進(jìn)制字符串
QByteArray ba("Hello");
QByteArray hex = ba.toHex(); // "48656c6c6f"(小寫)
QByteArray hexUpper = ba.toHex().toUpper(); // "48656C6C6F"2. 從十六進(jìn)制字符串還原
QByteArray restored = QByteArray::fromHex("48656c6c6f"); // "Hello"3. 數(shù)字與字節(jié)序列轉(zhuǎn)換
將數(shù)字轉(zhuǎn)為字節(jié)序列(需注意字節(jié)序,網(wǎng)絡(luò)傳輸用大端):
quint32 num = 0x12345678; // 轉(zhuǎn)為大端字節(jié)序列 char* bytes = reinterpret_cast<char*>(&num); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN qSwap(bytes[0], bytes[3]); qSwap(bytes[1], bytes[2]); #endif QByteArray ba(bytes, sizeof(num)); // 大端的0x12345678
Qt提供工具函數(shù)簡(jiǎn)化字節(jié)序處理:
quint32 num = 0x12345678;
QByteArray bigEndianBa = QByteArray::fromRawData(
reinterpret_cast<const char*>(&num), sizeof(num)
);
bigEndianBa = bigEndianBa.toBigEndian(); // 顯式轉(zhuǎn)大端(若系統(tǒng)是小端)八、與QString的關(guān)鍵區(qū)別
特性 | QByteArray | QString |
|---|---|---|
編碼 | 無(wú)編碼/8位編碼(ASCII/Latin1) | Unicode(UTF-16) |
用途 | 二進(jìn)制數(shù)據(jù)、8位文本 | 多語(yǔ)言文本 |
轉(zhuǎn)換 | 需指定編碼(如toUtf8()) | 自動(dòng)處理Unicode |
九、在流媒體開發(fā)中的典型應(yīng)用
QByteArray是流媒體處理的“瑞士軍刀”,常見場(chǎng)景:
協(xié)議解析:解析RTSP/RTP/RTCP包的頭部和負(fù)載(如提取RTP的序列號(hào)、時(shí)間戳)。
// 解析RTP頭部(12字節(jié)) QByteArray rtpPacket = ...; if (rtpPacket.size() < 12) return; quint8 version = rtpPacket[0] >> 6; // 版本號(hào)(第0字節(jié)高2位) quint16 seq = qFromBigEndian<quint16>(rtpPacket.constData() + 2); // 序列號(hào)(第2-3字節(jié),大端)
媒體數(shù)據(jù)封裝:封裝H.264/H.265的NALU到RTP payload,或打包MP4 box。
網(wǎng)絡(luò)IO:讀取UDP/TCP數(shù)據(jù),直接存儲(chǔ)到QByteArray中處理。
元數(shù)據(jù)處理:解析MP4/FLV文件的元數(shù)據(jù)(如時(shí)長(zhǎng)、分辨率),需處理字節(jié)級(jí)的tag結(jié)構(gòu)。
十、注意事項(xiàng)
- 字節(jié)序:網(wǎng)絡(luò)傳輸用大端(Big-Endian),本地處理需用
qToBigEndian/qFromBigEndian轉(zhuǎn)換。 - 內(nèi)存有效性:
constData()/data()返回的指針在QByteArray修改后可能失效,需謹(jǐn)慎使用。 - 編碼一致性:與
QString轉(zhuǎn)換時(shí)必須指定正確的編碼,否則會(huì)出現(xiàn)亂碼。 - 性能:批量操作(如
append大量數(shù)據(jù))時(shí),先reserve()預(yù)分配內(nèi)存,避免頻繁擴(kuò)容。
總結(jié)
QByteArray是Qt中處理字節(jié)數(shù)據(jù)和8位文本的核心類,其API設(shè)計(jì)兼顧了安全性與便捷性。在流媒體開發(fā)中,它能有效處理協(xié)議解析、數(shù)據(jù)封裝、網(wǎng)絡(luò)IO等關(guān)鍵場(chǎng)景,是嵌入式Linux流媒體方案的必備工具。
到此這篇關(guān)于Qt中QByteArray?類型的使用詳解的文章就介紹到這了,更多相關(guān)Qt QByteArray?類型使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
linux下c語(yǔ)言中隱藏進(jìn)程命令行參數(shù)(例如輸入密碼等高危操作)
啟動(dòng)程序很多時(shí)候用命令行參數(shù)可以很方便,做到簡(jiǎn)化一些配置,但是輸入用戶名密碼等操作,如果通過(guò)進(jìn)程查看工具直接看到密碼就太不安全了,這里就為大家分享一下方法2021-01-01
c++ qsort 與sort 對(duì)結(jié)構(gòu)體排序?qū)嵗a
這篇文章主要介紹了c++ qsort 與sort 對(duì)結(jié)構(gòu)體排序?qū)嵗a,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下2020-11-11
Qt實(shí)現(xiàn)http服務(wù)的示例代碼
這篇文章將為大家詳細(xì)講解有關(guān)Qt如何實(shí)現(xiàn)http服務(wù),小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲2023-04-04
DSP中浮點(diǎn)轉(zhuǎn)定點(diǎn)運(yùn)算--定點(diǎn)數(shù)的加減乘除運(yùn)算
本文主要介紹DSP中定點(diǎn)數(shù)的加減乘除運(yùn)算,很值得學(xué)習(xí)一下,需要的朋友可以參考一下。2016-06-06

