QByteArray 详细

1.QByteArray

QByteArray 是 Qt 框架中的一个类,用于处理字节数组。Qt 是一个跨平台的 C++ 图形用户界面库,广泛用于开发图形界面应用程序。QByteArray 提供了一种方便的方式来存储和操作字节数据。

以下是 QByteArray 的一些主要特点和用法:

  1. 动态数组QByteArray 是一个动态数组,可以动态地增长或缩小。
  2. 操作简便:它提供了许多方法来操作字节数据,如追加、插入、删除等。
  3. 与字符串的转换:可以轻松地将 QByteArray 转换为 QString 或标准 C++ 字符串,反之亦然。
  4. 内存高效:与直接使用标准 C++ 容器(如 std::vector<char>)相比,QByteArray 通常为 Qt 应用程序提供更优的内存管理和性能。
  5. 二进制数据处理:特别适合于处理二进制数据,如文件内容、网络通信数据等。

示例用法:

#include <QByteArray>  
#include <QDebug>  
  
int main() {  
    QByteArray byteArray;  
    byteArray.append("Hello, ");  
    byteArray.append("World!");  
    qDebug() << byteArray;  // 输出:Hello, World!  
    return 0;  
}

在这个简单的示例中,我们首先创建了一个空的 QByteArray 对象,然后向其中追加了两个字符串。最后,我们使用 qDebug() 打印出整个字节数组的内容。

2.QByteArray 添加int 数组

在 Qt 中,如果你想将一个 int 数组添加到 QByteArray 中,你需要先将 int 数组的每个元素转换为字节表示,然后再将这些字节添加到 QByteArray。这通常涉及到对每个 int 值进行序列化。以下是一个示例,展示了如何将一个 int 数组添加到 QByteArray

#include <QByteArray>  
#include <QDataStream>  
#include <QDebug>  
  
int main() {  
    QByteArray byteArray;  
    QDataStream out(&byteArray, QIODevice::WriteOnly);  
  
    int intArray[] = {1, 2, 3, 4, 5};  
    const int size = sizeof(intArray) / sizeof(intArray[0]);  
  
    for (int i = 0; i < size; ++i) {  
        out << intArray[i];  
    }  
  
    qDebug() << "Byte array size:" << byteArray.size();  
    qDebug() << "Byte array:" << byteArray.toHex();  
  
    return 0;  
}

在这个示例中,我使用了 QDataStream 来简化数据的序列化和反序列化过程。QDataStream 提供了一种方便的方式来读写复杂的数据结构。通过将 QDataStream 与 QByteArray 结合使用,你可以轻松地将基本数据类型(如 intfloatQString 等)写入字节数组。

注意,这种方法会将整数以二进制形式序列化到 QByteArray 中,而不是以可读的文本形式。如果你需要以文本形式存储整数,你可能需要将每个整数转换为字符串,然后再添加到 QByteArray

如果你需要以文本形式(例如,以逗号分隔的值)存储 int 数组,你可以这样做:

#include <QByteArray>  
#include <QString>  
#include <QStringList>  
#include <QDebug>  
  
int main() {  
    int intArray[] = {1, 2, 3, 4, 5};  
    const int size = sizeof(intArray) / sizeof(intArray[0]);  
    QStringList stringList;  
  
    for (int i = 0; i < size; ++i) {  
        stringList << QString::number(intArray[i]);  
    }  
  
    QByteArray byteArray = stringList.join(",").toUtf8();  
    qDebug() << "Byte array as text:" << byteArray;  
  
    return 0;  
}

在这个示例中,我首先将每个整数转换为 QString,然后使用 QStringList 来收集这些字符串,并最终将它们连接成一个以逗号分隔的字符串,然后转换为 QByteArray。这种方法将整数数组存储为可读的文本形式。

3.QByteArray 详解 

QByteArray是Qt框架中的一个重要类,它提供了一个字节数组的实现,用于存储原始字节数据。以下是对QByteArray的详细介绍:

一、基本概念与特点

  1. QByteArray是一个字节数组类,可以存储原始字节(包括'\0')和传统的8位'\0'终止字符串。
  2. 它在内部始终确保数据后面跟着'\0'终止符,这使得处理C风格的字符串变得简单。
  3. QByteArray使用了隐式共享(写入时复制)的技术,这有助于减少内存使用量,并避免不必要的数据复制,从而提高效率。

二、功能与方法

  1. QByteArray提供了丰富的功能来操作和转换字节数据,如append、insert、replace和remove等。这些方法使得对字节数组的处理变得非常灵活。
  2. 它还支持多种编码方式,如ASCII、UTF-8、UTF-16等,这使得处理不同编码的数据变得方便。

三、使用场景

QByteArray在处理文本和二进制文件、网络数据传输、串口通信等场景中非常有用。在这些情况下,经常需要处理原始的字节数据,而QByteArray提供了高效且方便的方式来存储和操作这些数据。

四、初始化与访问

  1. QByteArray可以通过多种方式进行初始化,如直接赋值、使用构造函数等。
  2. 访问QByteArray中的数据主要有四种方式:[]、at()、data[]和constData[]。其中,[]和data[]既可读又可写,而at()和constData[]仅为可读。如果仅需要读取数据,通过at()和constData[]访问速度最快,因为它们可以避免复制处理。

综上所述,QByteArray是一个功能强大且高效的字节数组类,适用于处理各种涉及原始字节数据的场景。

4.QByteArray 指定位置的指定长度的数据转换成指定的类型

要点

QByteArray subArray = data.mid(startIndex, length);  
bool ok;  
int value = subArray.toInt(&ok, 10); // 假设数据是十进制表示的整数

当需要将QByteArray中指定位置的指定长度数据转换成指定的类型时,可以遵循以下步骤:

  1. 确定位置和长度
    • 首先,明确要从QByteArray中提取数据的起始位置和长度。这些信息通常基于数据的结构和你要转换的具体需求。
  2. 提取子数组
    • 使用mid()函数从原始QByteArray中提取出感兴趣的部分。例如,QByteArray subArray = originalByteArray.mid(startIndex, length);,其中startIndex是起始位置,length是要提取的字节数。
  3. 数据转换
    • 根据目标类型,选择合适的方法进行转换。Qt提供了多种方式来转换QByteArray中的数据到特定类型。
      • 转换为整数:可以使用QByteArraytoInt()方法,但如果你从子数组中转换,可能需要先将其转换为字符串,然后使用QStringtoInt()方法。
      • 转换为浮点数:类似地,可以使用toDouble()toFloat()方法,或者先将子数组转换为字符串,然后使用QString的相应方法进行转换。
      • 转换为自定义数据结构:对于更复杂的数据结构,如结构体或类对象,你可能需要使用QDataStream来进行序列化和反序列化。
  4. 错误处理
    • 在进行数据转换时,应考虑到可能出现的错误,如数据格式不正确、数据溢出或转换失败等。Qt的转换函数通常提供了一个布尔参数来检查转换是否成功。
  5. 使用转换后的数据
    • 一旦数据被成功转换为目标类型,就可以在你的程序中使用这些数据了。
  6. 注意事项
    • 确保提取的子数组长度与目标类型所需的字节数相匹配。例如,一个int类型在大多数系统上占用4个字节,因此提取的子数组长度应为4。
    • 考虑数据的字节序(大端或小端)问题,特别是在跨平台通信或文件存储时。
  7. 示例代码
    假设我们有一个QByteArray包含了一些整数数据,并且我们知道每个整数占用4个字节,现在我们要提取第2个整数(从索引4开始,因为每个整数4个字节):
 

cpp复制代码

QByteArray data; // 假设这里已经填充了数据  
int startIndex = 4; // 第二个整数的起始位置  
int length = 4; // 整数的字节长度  
  
QByteArray subArray = data.mid(startIndex, length);  
bool ok;  
int value = subArray.toInt(&ok, 10); // 假设数据是十进制表示的整数  
if (ok) {  
    // 成功转换,使用value变量  
} else {  
    // 转换失败,处理错误情况  
}

请注意,上述代码是一个简化示例,实际应用中可能需要根据数据的具体情况进行调整。

5.QByteArray 为什么会把一个unsigned char 变成超大啊值,比如0xc5 变成了4294967237 

QByteArray 是 Qt 框架中用于处理字节数组的类。它内部使用 char 类型来存储数据,而 char 可以是有符号的或无符号的,这取决于编译器和平台。当你说“把一个 unsigned char 变成超大值,比如 0xc5 变成了 4294967237”时,这听起来像是在处理数据时发生了类型转换或解释错误。

首先,0xc5 是一个十六进制数,其十进制表示为 197。如果你在处理这个值时看到 4294967237,那么很可能是发生了以下几种情况之一:

  1. 符号扩展:如果你的 unsigned char 值被错误地转换为了一个有符号的 int 或更大的整数类型,并且该值大于 1270x7F),那么在转换为有符号整数时可能会发生符号扩展。在大多数系统中,char 类型默认是有符号的,范围从 -128 到 127。当你尝试将一个大于 127 的 unsigned char 值转换为 char 时,它会被解释为负数,然后当你再将它转换为更大的整数类型(如 int)时,这个负数会进行符号扩展,填充高位以保留符号。这可能导致你看到非常大的正数(如果你将这个有符号整数当作无符号整数来解释)。
  2. 错误的类型转换:在处理数据时,可能不正确地进行了类型转换,例如将 unsigned char 直接转换为 uint32_t 或其他更大的整数类型,而没有正确处理符号或无符号的转换。
  3. 显示或输出错误:在显示或输出这个值时,可能使用了错误的格式或方法,导致显示的值不正确。

为了解决这个问题,你需要确保在处理数据时保持正确的类型转换,并考虑数据的符号性。如果你在处理 QByteArray 中的数据时遇到问题,确保你在读取和转换数据时使用了正确的方法和类型。

例如,如果你从 QByteArray 中读取一个 unsigned char 值,你应该这样做:

QByteArray data; // 假设这里已经填充了数据
unsigned char value = static_cast<unsigned char>(data[index]); // 正确读取 unsigned char 值

注意,在处理字节数据时,特别是当数据可能大于 127 时,要特别注意符号扩展的问题。如果你需要将这个值转换为更大的整数类型,请确保使用无符号的整数类型来避免符号扩展。

uint32_t intValue = value; // 将 unsigned char 转换为 uint32_t,避免符号扩展

实验

实验1

1.代码

int test2(){
    QByteArray byteArray;
    QDataStream out(&byteArray, QIODevice::WriteOnly);
    unsigned short header = 0xc55c;
    out<<header;
    bool ok;

    QByteArray byteArray2 = byteArray.mid(0,2);
    short ret = byteArray2.toShort(&ok,10);
    qDebug()<<"ok:"<<ok;
    qDebug()<<"ret:"<<ret;
    short ret2 = byteArray.toShort(&ok,10);
    qDebug()<<"ok:"<<ok;
    qDebug()<<"ret2:"<<ret2;

    int ret3 = byteArray.toInt(&ok,10);
    qDebug()<<"ok:"<<ok;
    qDebug()<<"ret3:"<<ret3;
}

2.结果 

ok: false
ret: 0
ok: false
ret2: 0
ok: false
ret3: 0

实验2

代码

int test3(){
    QByteArray byteArray;
    QDataStream out(&byteArray, QIODevice::WriteOnly);
    int header = 20;
    out<<header;
    bool ok;

    int ret = byteArray.toInt(&ok,10);
    qDebug()<<"ok:"<<ok;
    qDebug()<<"ret3:"<<ret;
}

结果 

 ok: false
ret3: 0

实验3

代码

int test4(){
    QByteArray byteArray;
    QDataStream out(&byteArray, QIODevice::WriteOnly);
    unsigned short value = 0xc55c;
    out<<value;

    QDataStream in(&byteArray, QIODevice::ReadOnly);
    unsigned short vlaue2;
    in>>vlaue2;
    qDebug()<<"value:"<<vlaue2;
}

结果

 value: 50524

实验4

代码

//数据截取数据转换实验
int test5(){
    QByteArray byteArray;
    QDataStream out(&byteArray, QIODevice::WriteOnly);
    unsigned short value = 0xc55c;
    for(int i=0;i<5;i++){
        char cvalue = i;
        out<<cvalue;
    }
    out<<value;

    QByteArray byteArray2 = byteArray.mid(5,2);

    QDataStream in(&byteArray2, QIODevice::ReadOnly);
    unsigned short vlaue2;
    in>>vlaue2;
    qDebug()<<"vlaue2:"<<vlaue2;
}

结果

vlaue2: 50524

实验5

代码

//数据拷贝实验
int test6(){
    QByteArray byteArray;
    QDataStream out(&byteArray, QIODevice::WriteOnly);
    unsigned short value = 0xc55c;
    out<<value;
    for(int i=0;i<5;i++){
        char cvalue = i;
        out<<cvalue;
    }
    out<<value;
    //16进制输出
    qDebug()<<byteArray.toHex();

    char chars[9];

    std::memcpy(chars, byteArray.data(), 2);

    std::memcpy(chars+2, byteArray.data()+2, 5);

    std::memcpy(chars+7, byteArray.data()+7, 2);

    QByteArray byteArray2;
    QDataStream out2(&byteArray2, QIODevice::WriteOnly);
    for(int i=0;i<9;i++){
        out2<<chars[i];
    }


    qDebug()<<"change:"<<byteArray2.toHex();
}

结果

"c55c0001020304c55c"
change: "c55c0001020304c55c"

6.QByteArray 转换成unsigned short 

要点

QByteArray byteArray;    
  
// 创建一个QDataStream对象来从byteArray中读取数据  
QDataStream stream(&byteArray, QIODevice::ReadOnly);  
  
unsigned short value;  
stream >> value;

在Qt中,将QByteArray转换成unsigned short(即quint16)通常涉及读取字节数组中的特定数量的字节,并将其解释为一个unsigned short整数。这通常需要使用位操作和类型转换。以下是一个简单的示例,展示了如何从QByteArray中读取两个字节并将其转换为一个unsigned short

在Qt中,将QByteArray转换成unsigned short(即quint16)通常涉及读取字节数组中的特定数量的字节,并将其解释为一个unsigned short整数。这通常需要使用位操作和类型转换。以下是一个简单的示例,展示了如何从QByteArray中读取两个字节并将其转换为一个unsigned short:

cpp
#include <QByteArray>  
#include <QDataStream>  
  
// 假设你有一个QByteArray对象,里面包含了一些数据  
QByteArray byteArray;  
  
// ... 在这里填充byteArray数据 ...  
  
// 创建一个QDataStream对象来从byteArray中读取数据  
QDataStream stream(&byteArray, QIODevice::ReadOnly);  
  
unsigned short value;  
stream >> value;  
  
// 现在,value包含了从byteArray中读取的两个字节解释成的unsigned short值
在这个例子中,QDataStream被用来从QByteArray中读取数据。QDataStream能够处理字节顺序的问题,这对于跨平台的数据交换非常重要。

如果你想要手动处理这个过程,而不使用QDataStream,你可以这样做:

cpp
#include <QByteArray>  
  
// 假设你有一个QByteArray对象,里面包含了一些数据  
QByteArray byteArray;  
  
// ... 在这里填充byteArray数据 ...  
  
// 确保byteArray至少有2个字节  
if (byteArray.size() >= 2) {  
    unsigned char byte1 = static_cast<unsigned char>(byteArray[0]);  
    unsigned char byte2 = static_cast<unsigned char>(byteArray[1]);  
  
    // 将两个字节合并成一个unsigned short  
    // 假设byteArray中的数据是大端字节序(Big-Endian)  
    unsigned short value = (static_cast<unsigned short>(byte1) << 8) | byte2;  
  
    // 现在,value包含了从byteArray中读取的两个字节解释成的unsigned short值  
}
请注意,这个例子假设byteArray中的数据是以大端字节序存储的。如果你的数据是小端字节序(Little-Endian),你需要调整字节的顺序:

cpp
unsigned short value = byte2 | (static_cast<unsigned short>(byte1) << 8);
在处理二进制数据时,字节顺序(也称为端序)是一个重要的考虑因素,因为它会影响如何正确解释多个字节组成的数据类型。

在这个例子中,QDataStream被用来从QByteArray中读取数据。QDataStream能够处理字节顺序的问题,这对于跨平台的数据交换非常重要。

如果你想要手动处理这个过程,而不使用QDataStream,你可以这样做:

#include <QByteArray>  
  
// 假设你有一个QByteArray对象,里面包含了一些数据  
QByteArray byteArray;  
  
// ... 在这里填充byteArray数据 ...  
  
// 确保byteArray至少有2个字节  
if (byteArray.size() >= 2) {  
    unsigned char byte1 = static_cast<unsigned char>(byteArray[0]);  
    unsigned char byte2 = static_cast<unsigned char>(byteArray[1]);  
  
    // 将两个字节合并成一个unsigned short  
    // 假设byteArray中的数据是大端字节序(Big-Endian)  
    unsigned short value = (static_cast<unsigned short>(byte1) << 8) | byte2;  
  
    // 现在,value包含了从byteArray中读取的两个字节解释成的unsigned short值  
}

请注意,这个例子假设byteArray中的数据是以大端字节序存储的。如果你的数据是小端字节序(Little-Endian),你需要调整字节的顺序:

unsigned short value = byte2 | (static_cast<unsigned short>(byte1) << 8);

在处理二进制数据时,字节顺序(也称为端序)是一个重要的考虑因素,因为它会影响如何正确解释多个字节组成的数据类型。

7.QByteArray 输出 int

在 Qt 中,QByteArray 类提供了一种便捷的方式来处理字节序列。如果你想要将一个 int 值输出到 QByteArray 中,可以使用 QByteArray 的静态函数,如 number,来实现。下面是如何将 int 值转换为 QByteArray 的示例:

#include <QByteArray>  
#include <QDebug>  
  
int main() {  
    int value = 12345;  
    QByteArray byteArray = QByteArray::number(value);  
    qDebug() << byteArray; // 输出: "12345"  
  
    return 0;  
}

这里,number 函数将 int 值转换为字符串形式的 QByteArray。然后,可以使用 qDebug() 或其他方法来输出或使用这个 QByteArray

如果你需要将 int 以二进制形式而非字符串形式写入 QByteArray,你可以使用 QByteArray 的操作符 <<,如下所示:

#include <QByteArray>  
#include <QDataStream>  
#include <QDebug>  
  
int main() {  
    int value = 12345;  
    QByteArray byteArray;  
    QDataStream out(&byteArray, QIODevice::WriteOnly);  
    out << value;  
  
    qDebug() << byteArray.toHex(); // 输出值的16进制表示  
  
    return 0;  
}

在这个例子中,我们使用 QDataStream 将 int 值以二进制形式写入 QByteArraytoHex() 函数用于将 QByteArray 的内容输出为16进制字符串,以便于查看。

8.QByteArray 输出指定类型失败

在 Qt 中,QByteArray 本身并不直接支持将任意类型转换为字节序列,除了它提供的一些特定函数,如 number() 用于将数字转换为字符串形式的字节序列。如果你想要将指定类型(如自定义结构体或类)输出到 QByteArray 中,你需要自己实现转换逻辑。

一种常见的方法是使用 QDataStream,它可以将 Qt 支持的数据类型(包括自定义类型,只要它们注册了元类型系统)序列化为二进制形式,并存储到 QByteArray 中。以下是一个示例,展示了如何将一个自定义结构体序列化到 QByteArray 中:

#include <QByteArray>  
#include <QDataStream>  
#include <QDebug>  
  
struct MyStruct {  
    int x;  
    double y;  
};  
  
Q_DECLARE_METATYPE(MyStruct)  
  
int main() {  
    MyStruct value = {123, 45.67};  
    QByteArray byteArray;  
    QDataStream out(&byteArray, QIODevice::WriteOnly);  
    out << value;  
  
    // 现在 byteArray 包含了 value 的二进制表示  
    qDebug() << byteArray.toHex(); // 输出字节数组的16进制表示  
  
    // 读取回来  
    MyStruct readValue;  
    QDataStream in(&byteArray, QIODevice::ReadOnly);  
    in >> readValue;  
  
    qDebug() << "Read back:" << readValue.x << "," << readValue.y;  
  
    return 0;  
}

在这个例子中,我们首先声明了一个自定义结构体 MyStruct,并使用 Q_DECLARE_METATYPE() 宏将其注册到 Qt 的元类型系统中。然后,我们使用 QDataStream 将 MyStruct 的实例序列化到 QByteArray 中,并将其输出为16进制字符串。最后,我们演示了如何从 QByteArray 中读取回 MyStruct 的值。

如果你想要输出的是文本形式而不是二进制形式,你需要自己编写代码来将自定义类型的值转换为字符串,并使用 QByteArray 的构造函数或 append() 方法将其添加到字节数组中。

9.QByteArray.toInt 失败

QByteArray::toInt() 函数是用于将 QByteArray 中的字节序列转换为整数的。如果你在使用这个函数时遇到了失败,可能有几个原因:

  1. 字节序列的格式不正确QByteArray 中的数据可能不是有效的整数表示。例如,如果它包含非数字字符或数字的顺序不正确,toInt() 将无法正确解析它。

  2. 字节序(Endianness)问题:整数可以以不同的字节序存储在内存中(大端或小端)。如果 QByteArray 中的整数是以与你的系统不同的字节序存储的,toInt() 可能无法正确解析它。你可以使用 QDataStream 并设置正确的字节序来读取整数。

  3. 整数大小不匹配QByteArray::toInt() 默认假设整数是 32 位的。如果 QByteArray 中的整数是 16 位、64 位或其他大小,toInt() 将无法正确解析它。你可以使用 QDataStream 或其他方法来读取不同大小的整数。

  4. 超出范围:如果 QByteArray 中的整数超出了 int 类型可以表示的范围,toInt() 将无法正确解析它,并可能导致未定义的行为。

为了解决这个问题,你可以:

  • 确保 QByteArray 中的数据是有效的整数表示。
  • 使用 QDataStream 并设置正确的字节序来读取整数。
  • 检查整数的大小,并使用适当的方法来读取它。
  • 检查整数是否在 int 类型的范围内。

下面是一个使用 QDataStream 来读取整数的例子:

#include <QByteArray>  
#include <QDataStream>  
#include <QDebug>  
  
int main() {  
    // 假设我们有一个包含整数的 QByteArray  
    QByteArray byteArray;  
    QDataStream out(&byteArray, QIODevice::WriteOnly);  
    out << qint32(12345); // 写入一个 32 位整数  
  
    // 现在读取它回来  
    QDataStream in(&byteArray, QIODevice::ReadOnly);  
    qint32 value;  
    in >> value;  
  
    qDebug() << "Read value:" << value; // 输出读取的整数  
  
    return 0;  
}

在这个例子中,我们使用 QDataStream 来写入和读取一个 32 位整数。这样可以确保字节序和整数大小都是正确的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值