---
title: framework-cpp-qt-09-QByteArray
EntryName: framework-cpp-qt-09-QByteArray
date: 2020-04-16 16:32:30
categories:
tags:
- qt
- c/c++
---
章节描述:
QByteArray类提供存放二进制数据,什么数据都能保存。
介绍
QByteArray的本质上是一个字节数组。类似于unsigned char[]。
由于QByteArray封装的功能很多,使用起来比char*要方便的多,而就其内部实现来讲,它会保证所有的数据以'\0'结尾,使用隐式数据共享(copy-on-write)来减少内存消耗以及不必要的数据拷贝。
而QString是一个字符串,其内部其实也是unsigned char[],但是这个数组是用于保存unicode字符的数组。对QString进行操作的时候,是按照字符串的角度来进行调用的。QString自动完成了一些字符串到字节数组的转换工作。
初始化
QByteArray()
QByteArray(const char *data, int size = -1)
QByteArray(int size, char ch)
QByteArray(const QByteArray &other)
QByteArray(QByteArray &&other)
访问与赋值
访问QByteArray主要有4种方式,分别为[]、at()、data[]和constData[]。
其中[]和data[]为可读可写,at()和constData[]仅为可读。
如果仅是读,则通过at()和constData[]访问速度最快,因可避免复制处理。示例如下:
int main(int argc, char *argv[])
{
char buffer[7] = "Schips";
QByteArray ba(buffer);
qDebug()<< ba;
ba[0] = '0';
//ba.at(1) = '1'; // error
ba.data()[2] = '2';
qDebug()<<"[0]"<
qDebug()<<"[1]"< qDebug()<<"at(2)"< qDebug()<<"data(3)"< qDebug()<<"constData(4)"< qDebug()<<"constData(5)"< return 0; } 修改 QByteArray提供了很多修改字节的方法: append()/ prepend(),/insert(), replace(), remove()。如下所示 QByteArray & append(const QByteArray &ba) QByteArray & append(int count, char ch) QByteArray & append(const char *str) QByteArray & append(const char *str, int len) QByteArray & append(char ch) QByteArray & append(const QString &str) QByteArray & insert(int i, const QByteArray &ba) QByteArray & insert(int i, int count, char ch) QByteArray & insert(int i, const char *str) QByteArray & insert(int i, const char *str, int len) QByteArray & insert(int i, char ch) QByteArray & insert(int i, const QString &str) QByteArray & replace(int pos, int len, const QByteArray &after) QByteArray & replace(int pos, int len, const char *after, int alen) QByteArray & replace(int pos, int len, const char *after) QByteArray & replace(char before, const char *after) QByteArray & replace(char before, const QByteArray &after) QByteArray & replace(const char *before, const char *after) QByteArray & replace(const char *before, int bsize, const char *after, int asize) QByteArray & replace(const QByteArray &before, const QByteArray &after) QByteArray & replace(const QByteArray &before, const char *after) QByteArray & replace(const char *before, const QByteArray &after) QByteArray & replace(char before, char after) QByteArray & replace(const QString &before, const char *after) QByteArray & replace(char before, const QString &after) QByteArray & replace(const QString &before, const QByteArray &after) QByteArray & remove(int pos, int len) 例子: QByteArray x("and"); x.prepend("rock "); // x == "rock and" x.append(" roll"); // x == "rock and roll" x.replace(5, 3, "&"); // x == "rock & roll" x.remove(0, 3); // x == "k & roll" 查找 使用indexof函数从前向后获取索引第一次出现的位置 int indexOf(const QByteArray &ba, int from = 0) const int indexOf(const char *str, int from = 0) const int indexOf(char ch, int from = 0) const int indexOf(const QString &str, int from = 0) const 使用lastIndexof函数从后向前获取索引第一次出现的位置 int lastIndexOf(const QByteArray &ba, int from = -1) const int lastIndexOf(const char *str, int from = -1) const int lastIndexOf(char ch, int from = -1) const int lastIndexOf(const QString &str, int from = -1) const 例子: QByteArray x("crazy azimuths"); QByteArray y("az"); qDebug() << x.indexOf(y); // returns 2 qDebug() << x.indexOf(y, 1); // returns 2 qDebug() << x.indexOf(y, 10); // returns -1 qDebug() << x.indexOf(y); // returns 6 qDebug() << x.lastIndexOf(y); // returns 6 qDebug() << x.lastIndexOf(y, 6); // returns 6 qDebug() << x.lastIndexOf(y, 5); // returns 2 qDebug() << x.lastIndexOf(y, 1); // returns -1 使用contains 判断数据是否存在 bool contains(const QByteArray &ba) const bool contains(const char *str) const bool contains(char ch) const 数据转换与处理 常用转换包括:转为HEX、转为不同进制数值并显示、转为整型、浮点型等数值类型、大小写转换、转为字符串类型。 Hex转换 用于显示十六进制,这点在调试时特别有用,因为大多HEX码是没有字符显示的,如0x00、0x20等等; QByteArray text = QByteArray::fromHex("517420697320677265617421"); qDebug() << text.data(); // returns "Qt is great!" QByteArray raw ("Qt is great!"); QString hexText; hexText = raw.toHex(); qDebug() << hexText; 转为不同进制 转为不同进制数值并显示,如二进制、八进制、十进制和十六进制等; QByteArray &QByteArray::setNum(int n, int base = 10) // base : 进制 QByteArray QByteArray::number(int n, int base = 10) 尽管QByteArray是一个集合,但也可以作为一个特殊形式的数值用,其灵活的转换格式,可大大方便各种格式数据转换与显示的需求。如显示二进制和十六进制、显示科学计数和指定小数位的数值。示例如下: 把单个字符转为2-36进制数据格式: int n = 63; qDebug()< qDebug()< qDebug()< qDebug()< qDebug()< 按照指定进制格式直接复制,其中n可以是各类常见数值类型: QByteArray ba; int n = 63; ba.setNum(n); // ba == "63" ba.setNum(n, 16); // ba == "3f" 类型转换 转为整型、浮点型等数值类型; QByteArray toBase64() const QByteArray toBase64(QByteArray::Base64Options options) const CFDataRef toCFData() const double toDouble(bool *ok = nullptr) const float toFloat(bool *ok = nullptr) const QByteArray toHex() const QByteArray toHex(char separator) const int toInt(bool *ok = nullptr, int base = 10) const long toLong(bool *ok = nullptr, int base = 10) const qlonglong toLongLong(bool *ok = nullptr, int base = 10) const QByteArray toLower() const NSData * toNSData() const QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(), const QByteArray &include = QByteArray(), char percent = '%') const CFDataRef toRawCFData() const NSData *toRawNSData() const short toShort(bool *ok = nullptr, int base = 10) const std::string toStdString() const uint toUInt(bool *ok = nullptr, int base = 10) const ulong toULong(bool *ok = nullptr, int base = 10) const qulonglong toULongLong(bool *ok = nullptr, int base = 10) const ushort toUShort(bool *ok = nullptr, int base = 10) const 例子: QByteArray strInt("1234"); bool ok0; qDebug() << strInt.toInt(); // return 1234 qDebug() << strInt.toInt(&ok0,16); // return 4660, 默认把strInt作为16进制的1234,对应十进制数值为4660 QByteArray string("1234.56"); bool ok1; qDebug() << string.toInt(); // return 0, 小数均视为0 qDebug() << string.toInt(&ok1,16); // return 0, 小数均视为0 qDebug() << string.toFloat(); // return 1234.56 qDebug() << string.toDouble(); // return 1234.56 QByteArray str("FF"); bool ok2; qDebug() << str.toInt(&ok2, 16); // return 255, ok2 == true qDebug() << str.toInt(&ok2, 10); // return 0, ok2 == false, 转为十进制失败 大小写转换 QByteArray若为带大小写的字符串,可通过toUpper()和toLower()方法实现大小写转换,示例如下: QByteArray x("Qt by THE QT COMPANY"); QByteArray y = x.toLower(); // y == "qt by the qt company" QByteArray z = x.toUpper(); // z == "QT BY THE QT COMPANY" 转为字符串类型 QByteArray与QString互转极为简单,二者从本质上类似,都是连续存储,区别是前者可以存无法显示的字符,后者只存可显示的字符。如QByteArray可以存0x00-0x19,而QString则存储0x20-0x7E(可参见ASCII表)的字符。 QByteArray ba1("abc123"); QString str1 = ba1; //或str1.prepend(ba1); qDebug()< //输出:"abc123" QString str2("abc123"); QByteArray ba2 = str2.toLatin1(); qDebug()< //输出:"abc123" 申请内存 QByteArray可以自动调整内存大小,如果希望提高性能,则可以使用reseve()函数来主动分动一段内存空间, 如: QByteArray byteArray; byteArray.reserve(30); /*!<申请30个字节的空间*/ 该内存空间不会主动释放,须使用以下方式进行释放 byteArray.squeeze(); /*!<释放内存*/ 与结构体之间的转换 一般用于可用于网络传输、读写等。 结构体转QByteArray #include #include // 定义某个结构体 typedef struct _Header{ int channel; int type; } Header; ... // 在某处的函数调用中 { // 声明并赋值结构体 Header header ={0}; header.channel = 1001; header.type = 1; // 声明QByteArray QByteArray array; // 使用 有关的赋值函数,例如 append 或者 insert 来进行操作 array.append((char*)&Header, sizeof(Header)); } QByteArray转结构体 // 紧接着上面的例子。 // 通过 QByteArray::data 方法获取 地址内容 的首地址 Header *getHeader = (Header*)array.data(); // 此后,正常操作数据即可。例如,将其赋值到 某个 结构体中 Header header_out ={0}; memcpy(&header_out, getHeader, sizeof(header_out)); // 验证一下 qDebug() << header_out.channel; qDebug() << header_out.type; 例程 #include #include #include typedef struct Header{ int channel; int type; } Header; typedef struct Msg{ Header header; char content[128]; friend QDebug operator << (QDebug os, Msg msg){ os << "(" << " channel:" << msg.header.channel << " type:" << msg.header.type << " content:" << msg.content << " )"; return os; } }Msg; typedef struct PeerMsg{ PeerMsg(const int &ip, const int &por) : ipV4(ip), port(por) {} int ipV4; int port; friend QDebug operator << (QDebug os, PeerMsg msg){ os << "( " << " ipV4:" << QString::number(msg.ipV4) << " port:" << QString::number(msg.port) << " )"; return os; } } PeerMsg; int main(void) { Msg msg; msg.header.channel = 1001; msg.header.type = 1; memcpy(msg.content, "ABCDEFG", sizeof("ABCDEFG")); qDebug() << msg; QByteArray array; array.append((char*)&msg, sizeof(msg)); Msg *getMsg = (Msg*)array.data(); qDebug() << *getMsg; QByteArray totalByte; PeerMsg peerMsg(123456, 10086); totalByte.append((char*)&peerMsg, sizeof(PeerMsg)); totalByte.append(array, array.size()); PeerMsg *getByte = (PeerMsg*)totalByte.data(); qDebug() << *getByte; QByteArray contentmsg = totalByte.right(totalByte.size() - sizeof(*getByte)); Msg *getMsg2 = (Msg*)contentmsg.data(); qDebug() << *getMsg2; return 0; } 输出结果: ( channel: 1001 type: 1 content: ABCDEFG ) ( channel: 1001 type: 1 content: ABCDEFG ) ( ipV4: "123456" port: "10086" ) ( channel: 1001 type: 1 content: ABCDEFG )