参考:
Using QByteArray - Qt Wiki
https://wiki.qt.io/Using_QByteArray
Qt总结之十五:QByteArray详解-CSDN博客
https://blog.csdn.net/Aidam_Bo/article/details/85778012
QT学习:09 QByteArray - schips - 博客园
https://www.cnblogs.com/schips/p/framework-cpp-qt-09-QByteArray.html
QT之QByteArry - 知乎
https://zhuanlan.zhihu.com/p/630368775
本地环境:
win10专业版,64位,Qt 5.12
代码已经测试通过。其他例子日后更新。
在 Qt5 中,QByteArray
类型提供了一些方便的方法用于数据类型转换和处理字节数组。
- 不包含encoding信息,也不会自动decode
- 转化为QString时需要指明encoding,比如
QString::fromUtf8()
是将QByteArray
转为utf8编码的QString
- 在处理网络数据的情况下,QByteArray 类型会自动处理不同系统中的大端小端问题
- 由于历史原因,QByteArray区分了一个Null byte 和 empty byte。建议始终使用
isEmpty()
初始化
- 使用
const char*
。此时会保留末尾的'\0'
,但是size()
还是实际的字符数目5。实际上,内部是可以有'\0'
的名单上末尾不行。QByteArray ba("Hello");
- 逐个字节填充。注意:调用
resize()
后,新分配的字节的值是未定义的,需要设置。QByteArray ba; ba.resize(5); ba[0] = 0x3c; ...
- 所有字节设置为同一个值:
ba.fill(0x3c);
。如果带第二个参数,就是指定填充后的长度 - 另外一些常用的:
- QByteArray::fromRawData(const char* data, int size):该函数将给定的字符数据和大小创建一个 QByteArray 对象。指向原始数据,no copy
- QByteArray::fromStdString(const std::string& str):将标准 C++ 字符串转换为 QByteArray。
- QByteArray::fromHex(const QString& hexEncoded):将十六进制字符串转换为 QByteArray。
- QByteArray::fromBase64(const QByteArray& base64):将 Base64 编码的数据转换为 QByteArray。
- int转化为QByteArray:第二个参数是base,默认是10,取值范围2~36。
.setNum()
也是类似int n = 63; QByteArray::number(n, 16).toUpper(); // returns "3F" QByteArray str("FF"); bool ok2; qDebug() << str.toInt(&ok2, 10); // return 0, ok2 == false, 转为十进制失败
申请内存
QByteArray可以自动调整内存大小,如果希望提高性能,则可以使用reseve()
函数来主动分动一段内存空间, 如:
QByteArray byteArray;
byteArray.reserve(30); // 申请30个字节的空间
该内存空间不会主动释放,必须使用squeeze()
释放:
byteArray.squeeze(); // 释放内存
访问
访问单个字节
- 访问方式共有四种:
[]
、data[]
和at()
、constData[]
,前两种可读可写,后两种只读。 - 如果是只读访问,应该使用
at()
(或者constData[]
),因为at()
比[]
快(不会导致深拷贝)。
for (int i = 0; i < ba.size(); ++i) {
if (ba.at(i) >= 'a' && ba.at(i) <= 'f') {...}
}
截取几个字节
提取多个字节使用left()
,right()
,mid()
(类似QString
)。
获取指向实际数据的指针
使用data()
或constData()
。指针保持有效,直到在QByteArray上调用了非const函数。
char *data = ba.data();//返回一个指向字节数组ba的数据指针,指向第一个字符
qDebug() << ba.data();//打印整个字符
while (*data)
{
cout << "[" << *data << "]" << endl;
++data;
}
查找
indexOf()
和lastIndexOf()
。跟QString
的一样,没什么好说的。- 判断是否包含某个子串:
contains()
- 查找并替换所有:
replace()
- 已经重载
<,<=,==,>=
等运算符,不常用。QString::localeAwareCompare()
是排序用户界面字符串的更好选择。
修改
QByteArray x("and");
x.prepend("rock "); // x == "rock and" 前面添加
x.append(" roll"); // x == "rock and roll" 后面添加
x.replace(5, 3, "&"); // x == "rock & roll" 替换。第二个参数是被替换的长度
x.insert(0, 'i'); // irock & roll
x.remove(0, 1); // rock & roll
删除空白字符:
- 空白字符指的是
\n
,\t
, trimmed()
是去除两端的空白字符simplified()
除了去除两端还会将中间的多个连续空格换成单个,别的单个换成space
QByteArray x("\ta\naaa c \n");
qDebug() << x.trimmed() << endl; // "a\naaa c"
qDebug() << x.simplified() << endl; // "a aaa c"
转化
- 转大小写:
.toLower()
.toUpper()
- 转为double、float、int等:
.toDouble()
.toFloat()
.toInt()
- 转为16进制编码版本:
.toHex()
- 转为
std::string
:.toStdString()
为什么toInt()错误
我有一个文档,大概内容是:
红线标的4个字节需要转为int,应该返回14,但是:
QFile file("://resources/data/pUC57-Amp.dna");
if (file.open(QIODevice::ReadOnly)) {
QByteArray byteArray = file.readAll();
file.close();
// 读取一些基础信息
int ptr = 0;
// 读第一个字符,应该是\t
QString strFirstChr = byteArray.mid(0, ptr++); // 模拟移动
qDebug() << byteArray.mid(0, 1) << endl;
bool isok;
QByteArray a = byteArray.mid(ptr, 4);
// 输出:"\x00\x00\x00\x0E" 0 false
qDebug() << a << a.toInt(&isok, 16) << isok << endl;
}
修改最后一句代码:
qDebug() << a << a.toHex().toInt(&isok, 16) << isok << endl;
因为需要先转成十六进制然后再转。直接toInt(),不论是否指明base=16都不会正确转化。
qDebug() << a << a.toInt() << isok << endl;
// "\x00\x00\x00\x0E" 0 true