QT学习:09 QByteArray

QT学习:09 QByteArray

---

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]"< 0

qDebug()<<"[1]"<

qDebug()<<"at(2)"< 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 )

相关推荐