Qt中QByteArray​类型的使用详解

 更新时间:2025年12月14日 14:39:35   作者:华丽的周遭  
QByteArray是Qt中处理原始字节数据和8位字符串的核心容器类,本文就来详解的介绍一下QByteArray​类型的使用,感兴趣的可以了解一下

在Qt开发中,QByteArray​ 是处理原始字节数据(Raw Bytes)、8位字符串(如ASCII/Latin-1/UTF-8)和二进制 payload​ 的核心容器类。它类似C++的std::vector<char>或C风格字符串,但提供了更安全、更便捷的API,且与Qt生态(如QString、网络模块、文件IO)深度集成。

一、核心定位

QByteArray的设计目标是:

  • 存储无编码的二进制数据(如图像像素、RTP payload、加密数据);
  • 处理8位编码的字符串(如HTTP头部的ASCII文本、RTSP协议的UTF-8 URL);
  • 替代C风格的char[],避免手动内存管理和越界风险。

二、基础操作:构造与赋值

QByteArray支持多种初始化方式,覆盖常见场景:

1. 空对象

QByteArray ba; // 空字节序列,size=0

2. 从C风格字符串构造

const char* cstr = "Hello, Qt!";
QByteArray ba(cstr); // 内容:"Hello, Qt!"(自动添加'\0'?不,QByteArray不强制以'\0'结尾,除非显式包含)

3. 从QString转换(编码敏感)

需指定编码(如UTF-8/Latin1),将Unicode字符串转为字节序列:

QString str = "你好,Qt!";
QByteArray utf8Ba = str.toUtf8();    // UTF-8编码的字节序列
QByteArray latin1Ba = str.toLatin1();// Latin1编码(每个字符1字节)

反向转换(字节序列→QString):

QString fromUtf8 = QString::fromUtf8(utf8Ba);   // 转回Unicode字符串
QString fromLatin1 = QString::fromLatin1(latin1Ba);

4. 填充重复字符

QByteArray filledBa = QByteArray::fromRawData("ABCD", 4); // 从原始数据创建(不复制)
filledBa.fill('X', 3); // 修改为"XXXD"(size=4,前3个字符替换为'X')
// 或:QByteArray ba; ba.fill('Y', 5); // 创建5个'Y':"YYYYY"

5. 静态工厂方法(常用)

fromHex():将十六进制字符串转为字节序列

QByteArray hex = QByteArray::fromHex("48656c6c6f"); // 对应"Hello"的字节(0x48=H, 0x65=e...)

fromStdString():将std::string转为QByteArray

std::string stdStr = "std::string";
QByteArray ba = QByteArray::fromStdString(stdStr);

三、数据访问:读写与遍历

QByteArray提供安全高效的访问方式,避免越界:

1. 下标访问

  • at(int i):只读,返回const char&,越界时触发断言(Debug模式)。
  • operator[](int i):可读写,返回char&,Debug模式下越界检查,Release模式未定义。
QByteArray ba("Hello");
char c1 = ba.at(1);    // 'e'(只读)
ba[0] = 'h';           // 修改为"hello"

2. 原始指针访问

  • constData():返回const char*,指向内部数据(不修改)。
  • data():非const对象返回char*(可修改),const对象返回const char*

⚠️ 注意:若QByteArray修改(如append)导致内存重新分配,旧指针会失效

const char* ptr = ba.constData(); // 指向"h"
ba.append("ello");                // 内存可能重新分配
// ptr 此时可能指向无效内存!

3. 遍历字节

// 方式1:基于下标
for (int i = 0; i < ba.size(); ++i) {
    qDebug() << static_cast<int>(ba[i]); // 打印每个字节的整数值
}
 
// 方式2:迭代器(Qt风格)
for (auto it = ba.begin(); it != ba.end(); ++it) {
    qDebug() << *it;
}

四、容量与内存管理

QByteArray动态管理内存,支持预分配和收缩:

1. 容量查询

  • size():当前存储的字节数。
  • isEmpty():等价于size() == 0,更高效。
  • capacity():当前分配的内存容量(≥size())。

2. 预分配内存

提前预留空间,避免频繁扩容:

QByteArray ba;
ba.reserve(1024); // 预分配1024字节,后续append无需重新分配
for (int i = 0; i < 1000; ++i) {
    ba.append('a');
}

3. 收缩内存

若容量远大于实际大小,可释放多余内存:

ba.resize(10);    // 缩小size到10
ba.squeeze();     // capacity变为10,释放多余内存

4. 清空数据

ba.clear(); // size=0,capacity不变

五、修改操作:增删改查

QByteArray提供丰富的方法处理字节序列:

1. 追加(Append)

QByteArray ba("Hello");
ba.append(" World");      // "Hello World"
ba.append('!');
ba.append(QByteArray::fromHex("00FF")); // 追加两个十六进制字节:0x00, 0xFF

2. 插入(Insert)

ba.insert(5, ", Qt");     // 在第5位插入,变成"Hello, Qt World!"

3. 删除(Remove)

ba.remove(5, 4);
// 删除从第5位开始的4个字符(", Qt"),回到"Hello World!"

4. 替换(Replace)

ba.replace("World", "Qt");    // "Hello Qt!"
ba.replace(6, 2, "Qt");       // 从第6位替换2个字符为"Qt",同上
ba.replace('l', 'L');         // 全局替换:'Hello Qt!' → 'HeLLo Qt!'

5. 子串提取

  • left(int n):取前n个字节。
  • right(int n):取后n个字节。
  • mid(int pos):从pos到末尾。
  • mid(int pos, int len):从pos取len个字节。
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):返回第一个匹配的索引(-1表示未找到)。
  • lastIndexOf(const QByteArray& str):返回最后一个匹配的索引。
  • startsWith(const QByteArray& prefix):是否以prefix开头。
  • endsWith(const QByteArray& suffix):是否以suffix结尾。
QByteArray ba("Hello World");
bool hasHello = ba.contains("Hello"); // true
int idx = ba.indexOf("World");        // 6
bool startsWithHe = ba.startsWith("He"); // true

2. 比较

  • operator==:内容+大小完全一致才相等。
  • operator<:按字典序比较(字节级)。
  • equals(const QByteArray& other):等价于==
QByteArray a("abc");
QByteArray b("abd");
bool equal = (a == b); // false
bool less = (a < b);   // true

七、编码与转换

QByteArray常用来处理编码转换,尤其是与网络协议、文件格式交互时:

1. 转为十六进制字符串

QByteArray ba("Hello");
QByteArray hex = ba.toHex(); // "48656c6c6f"(小写)
QByteArray hexUpper = ba.toHex().toUpper(); // "48656C6C6F"

2. 从十六进制字符串还原

QByteArray restored = QByteArray::fromHex("48656c6c6f"); // "Hello"

3. 数字与字节序列转换

将数字转为字节序列(需注意字节序,网络传输用大端):

quint32 num = 0x12345678;
// 转为大端字节序列
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提供工具函数简化字节序处理:

quint32 num = 0x12345678;
QByteArray bigEndianBa = QByteArray::fromRawData(
    reinterpret_cast<const char*>(&num), sizeof(num)
);
bigEndianBa = bigEndianBa.toBigEndian(); // 显式转大端(若系统是小端)

八、与QString的关键区别

特性

QByteArray

QString

编码

无编码/8位编码(ASCII/Latin1)

Unicode(UTF-16)

用途

二进制数据、8位文本

多语言文本

转换

需指定编码(如toUtf8())

自动处理Unicode

九、在流媒体开发中的典型应用

QByteArray是流媒体处理的“瑞士军刀”,常见场景:

协议解析:解析RTSP/RTP/RTCP包的头部和负载(如提取RTP的序列号、时间戳)。

// 解析RTP头部(12字节)
QByteArray rtpPacket = ...;
if (rtpPacket.size() < 12) return;
quint8 version = rtpPacket[0] >> 6; // 版本号(第0字节高2位)
quint16 seq = qFromBigEndian<quint16>(rtpPacket.constData() + 2); // 序列号(第2-3字节,大端)

媒体数据封装:封装H.264/H.265的NALU到RTP payload,或打包MP4 box。

网络IO:读取UDP/TCP数据,直接存储到QByteArray中处理。

元数据处理:解析MP4/FLV文件的元数据(如时长、分辨率),需处理字节级的tag结构。

十、注意事项

  • 字节序:网络传输用大端(Big-Endian),本地处理需用qToBigEndian/qFromBigEndian转换。
  • 内存有效性constData()/data()返回的指针在QByteArray修改后可能失效,需谨慎使用。
  • 编码一致性:与QString转换时必须指定正确的编码,否则会出现乱码。
  • 性能:批量操作(如append大量数据)时,先reserve()预分配内存,避免频繁扩容。

总结

QByteArray是Qt中处理字节数据8位文本的核心类,其API设计兼顾了安全性与便捷性。在流媒体开发中,它能有效处理协议解析、数据封装、网络IO等关键场景,是嵌入式Linux流媒体方案的必备工具。

到此这篇关于Qt中QByteArray​类型的使用详解的文章就介绍到这了,更多相关Qt QByteArray​类型使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解C语言之顺序表

    详解C语言之顺序表

    这篇文章主要为大家介绍了C语言的顺序表,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • linux下c语言中隐藏进程命令行参数(例如输入密码等高危操作)

    linux下c语言中隐藏进程命令行参数(例如输入密码等高危操作)

    启动程序很多时候用命令行参数可以很方便,做到简化一些配置,但是输入用户名密码等操作,如果通过进程查看工具直接看到密码就太不安全了,这里就为大家分享一下方法
    2021-01-01
  • c++ qsort 与sort 对结构体排序实例代码

    c++ qsort 与sort 对结构体排序实例代码

    这篇文章主要介绍了c++ qsort 与sort 对结构体排序实例代码,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-11-11
  • Qt实现http服务的示例代码

    Qt实现http服务的示例代码

    这篇文章将为大家详细讲解有关Qt如何实现http服务,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获
    2023-04-04
  • C++中的对象指针总结

    C++中的对象指针总结

    以下是对C++中的对象指针进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • 算法详解之分支限界法的具体实现

    算法详解之分支限界法的具体实现

    这篇文章主要介绍了算法详解之分支限界法的具体实现,需要的朋友可以参考下
    2014-02-02
  • DSP中浮点转定点运算--定点数的加减乘除运算

    DSP中浮点转定点运算--定点数的加减乘除运算

    本文主要介绍DSP中定点数的加减乘除运算,很值得学习一下,需要的朋友可以参考一下。
    2016-06-06
  • C语言数据存储详解

    C语言数据存储详解

    在本篇文章里小编给大家整理的是关C语言数据存储,小编觉得这篇文章写的很不错,有需要的朋友们可以学习参考下,希望能够给你带来帮助
    2021-10-10
  • C语言线性表之双链表详解

    C语言线性表之双链表详解

    这篇文章主要为大家详细介绍了C语言线性表之双链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++中的可移植性和跨平台开发教程详解

    C++中的可移植性和跨平台开发教程详解

    这篇文章主要为大家介绍了C++中的可移植性和跨平台开发教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05

最新评论