介紹
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"
轉為字符串類型
QByteArray
與QString
互轉極為簡單,二者從本質上類似,都是連續存儲,區別是前者可以存無法顯示的字符,后者只存可顯示的字符。如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 )