---
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]"<<ba[0]; //[] S -> 0
qDebug()<<"[1]"<<ba[1]; //[] c
qDebug()<<"at(2)"<<ba.at(2); //at() h -> 2
qDebug()<<"data(3)"<<ba.data()[3]; //data() i
qDebug()<<"constData(4)"<<ba.constData()[4]; //constData() p
qDebug()<<"constData(5)"<<ba.constData()[5]; //constData() s 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()<<QByteArray::number(n); // returns "63"
qDebug()<<QByteArray::number(n, 16); // returns "3f"
qDebug()<<QByteArray::number(n, 16).toUpper(); // returns "3F"
qDebug()<<QByteArray::number(n, 2); // returns "111111"
qDebug()<<QByteArray::number(n, 8); // returns "77"

按照指定进制格式直接复制,其中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"

转为字符串类型

QByteArrayQString互转极为简单,二者从本质上类似,都是连续存储,区别是前者可以存无法显示的字符,后者只存可显示的字符。如QByteArray可以存0x00-0x19,而QString则存储0x20-0x7E(可参见ASCII表)的字符。

QByteArray ba1("abc123");
QString str1 = ba1;
//或str1.prepend(ba1);
qDebug()<<str1 ;
//输出:"abc123" QString str2("abc123");
QByteArray ba2 = str2.toLatin1();
qDebug()<<ba2;
//输出:"abc123"

申请内存

QByteArray可以自动调整内存大小,如果希望提高性能,则可以使用reseve()函数来主动分动一段内存空间, 如:

QByteArray byteArray;
byteArray.reserve(30); /*!<申请30个字节的空间*/

该内存空间不会主动释放,须使用以下方式进行释放

byteArray.squeeze();   /*!<释放内存*/

与结构体之间的转换

一般用于可用于网络传输、读写等。

结构体转QByteArray

#include <QByteArray>
#include <QDebug> // 定义某个结构体
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 <QByteArray>
#include <QDebug>
#include <stdlib.h> 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 )

QT学习:09 QByteArray的更多相关文章

  1. Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON

    Home / Qt 学习之路 2 / Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON  豆子 ...

  2. Qt 学习之路 2(63):使用 QJson 处理 JSON

    Home / Qt 学习之路 2 / Qt 学习之路 2(63):使用 QJson 处理 JSON Qt 学习之路 2(63):使用 QJson 处理 JSON  豆子  2013年9月9日  Qt ...

  3. Qt 学习之路 2(60):使用 DOM 处理 XML

    Qt 学习之路 2(60):使用 DOM 处理 XML  豆子  2013年8月3日  Qt 学习之路 2  9条评论 DOM 是由 W3C 提出的一种处理 XML 文档的标准接口.Qt 实现了 DO ...

  4. Qt 学习之路 2(53):自定义拖放数据

    Qt 学习之路 2(53):自定义拖放数据 豆子  2013年5月26日  Qt 学习之路 2  13条评论上一章中,我们的例子使用系统提供的拖放对象QMimeData进行拖放数据的存储.比如使用QM ...

  5. Qt 学习之路 2(38):存储容器

    Qt 学习之路 2(38):存储容器 豆子 2013年1月14日 Qt 学习之路 2 38条评论 存储容器(containers)有时候也被称为集合(collections),是能够在内存中存储其它特 ...

  6. Qt 学习之路 2(35):文件

    Qt 学习之路 2(35):文件 豆子 2013年1月5日 Qt 学习之路 2 12条评论 文件操作是应用程序必不可少的部分.Qt 作为一个通用开发库,提供了跨平台的文件操作能力.从本章开始,我们来了 ...

  7. qt学习(三):鼠标图标改变

    qt学习 (三):鼠标图标改变 当你进入一个美好的qt软件场景,比如游戏,电脑的黑白图标会让程序逊色不少, 1改图标要加光标的头文件, 2 载入光标图, 3 再设置改光标就可以了 1在头文件中加 #i ...

  8. JavaScript学习09 函数本质及Function对象深入探索

    JavaScript学习09 函数本质及Function对象深入探索 在JavaScript中,函数function就是对象. JS中没有方法重载 在JavaScript中,没有方法(函数)重载的概念 ...

  9. QT学习第1天

    QT学习第一天  坚持住!! 一 Qt概述 1.Qt发展历史 (1)1991年诞生(Haavard Nord/Eirik Chambe-Eng), (2)1994年创立Troll Tech(奇趣科技) ...

  10. 【转载】分享一些Qt学习资源,欢迎下载

    资源来源:http://bbs.csdn.net/topics/390358737 经过我一翻整理,把一些我收集到的Qt学习资源分享给大家,主要适合新手,老鸟可以直接忽略我.要说明一下,很多资源都是在 ...

随机推荐

  1. 一个随时跟新的css库

    1.一个选中阴影的样式 .select border: 1px solid #4d92f7; box-shadow: 0px 0px 15px rgba(0,50,122,.15); 2.一个三栏渐变 ...

  2. 什么是SQL 语句中相关子查询与非相关子查询

    1.什么是SQL子查询 要理解相关子查询和非相关子查询,我们得首先理解什么是子查询,子查询是指在一个查询语句中嵌套的另一个查询语句. 子查询可以嵌套在其他查询语句中,如 SELECT.INSERT.U ...

  3. 一个 5.2k+ Star 的微服务商城系统

    大家好,我是 Java陈序员. 自从微服务开始流行之后,各种商城系统.外卖系统可是层出不穷.面试的时候人人都说做过商城系统,导致现在一听电商系统就是烂大街的项目. 黑格尔曾经说过:存在即合理.电商系统 ...

  4. 再聊解除HiddenApi限制

    炒冷饭,再聊聊大家都知晓的隐藏接口的限制解除. 说明 由于我们容器产品的特性,需要将应用完整的运行起来,所以必须涉及一些隐藏接口的反射调用,而突破反射限制则成为我们实现的基础.现将我们的解决方案分享给 ...

  5. 开源相机管理库Aravis例程学习(六)——camera-features

    目录 简介 例程代码 函数说明 arv_camera_get_integer arv_camera_get_string 简介 本文针对官方例程中的:04-camera-features做简单的讲解. ...

  6. element Tree 树形控件

    文档地址 https://element.eleme.cn/#/zh-CN/component/tree 代码地址 https://gitee.com/wBekvam/vue-shop-admin/b ...

  7. Golang 之 casbin(权限管理)

    目录 1. 权限管理 官网 编辑器测试 1.1.1. 特征 Casbin的作用 Casbin不执行的操作 1.1.2. 怎么运行的 1.1.3. 安装 1. 示例代码 xormadapter 2. 示 ...

  8. Premiere cc 2019之声音处理

    目录 deepin录视频 调整声道 查看声音轨道 转化格式 提取二声道的台词音,或者背景音 降噪 1.无需AU!PR自带音频模块完美实现降噪.增强人声.模拟环境 2.Adobe audition中降噪 ...

  9. Python基础知识——缩进、标识符、保留字

    标识符 标识符就是程序中,使用的各种名称,例如:变量名.常量名.类名等等. 在 Python 中,对标识符格式的要求与 C/C++.Java 等差不多: 第一个字符必须是字母表中的字母或下划线 _ ; ...

  10. vue特殊attribute-key

    官方说明:如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地复用相同类型元素的算法.而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在 ...