qt-通信协议基础-QStirng转QByteArray-与字节序互动

提问

QStirng转QByteArray是大端字节序,还是小端字节序?

分析

在 Qt 中,QString 转换为 QByteArray 的字节序(大端或小端)取决于编码方式,而不是直接由 QString 或 QByteArray 本身决定。

  • QString 和 QByteArray 的本质
    • QString 是 Unicode 字符串(默认 UTF-16 编码,内部使用 QChar,即 16 位无符号整数)。
    • QByteArray 是原始字节数组,不包含任何内置的字节序信息。它的字节顺序由编码转换时的规则决定。
  • QString 转 QByteArray 的字节序
    • 默认行为:
      当使用 QString::toUtf8()、toLatin1() 或 toLocal8Bit() 等方法时,转换的是字符的编码(如 UTF-8、ISO-8859-1 等),不涉及多字节数值的字节序问题。
      原因:这些编码是按字节存储的,每个字符的字节顺序是固定的(例如 UTF-8 是变长编码,无字节序问题;Latin1 是单字节编码)。
    • UTF-16 编码的字节序:
      如果显式使用 QString::toUtf16(),返回的 QByteArray 会包含 UTF-16 编码的字节流,此时字节序由系统字节序或显式指定的字节序标记(BOM)决定:
    • 无 BOM:默认使用系统字节序(通过 QSysInfo::ByteOrder 查询,可能是 QSysInfo::BigEndian 或 QSysInfo::LittleEndian)。
    • 有 BOM:如果传入 QString::toUtf16() 的参数为 withBom = true,会在开头添加 2 字节的 BOM(0xFEFF 表示大端序,0xFFFE 表示小端序)。
cpp 复制代码
QString str = "Hello";

// 默认系统字节序(无 BOM)
QByteArray utf16Default = str.toUtf16(); // 字节序取决于系统

// 显式添加 BOM(根据 BOM 决定字节序)
QByteArray utf16WithBom = str.toUtf16(true); // 包含 BOM,可明确字节序
  • 如何控制字节序?
    强制小端序或大端序:如果需要明确指定字节序,可以手动处理 QString 的 UTF-16 数据。
cpp 复制代码
QString str = "Hello";

// 转换为 UTF-16 小端序(无 BOM)
QByteArray utf16LE;
const QChar *chars = str.unicode();
for (int i = 0; i < str.length(); ++i) {
    quint16 ch = chars[i];
    // 小端序:低字节在前
    utf16LE.append(static_cast<char>(ch & 0xFF));       // 低字节
    utf16LE.append(static_cast<char>((ch >> 8) & 0xFF)); // 高字节
}

// 转换为 UTF-16 大端序(无 BOM)
QByteArray utf16BE;
for (int i = 0; i < str.length(); ++i) {
    quint16 ch = chars[i];
    // 大端序:高字节在前
    utf16BE.append(static_cast<char>((ch >> 8) & 0xFF)); // 高字节
    utf16BE.append(static_cast<char>(ch & 0xFF));       // 低字节
}
  • 使用 QDataStream 控制字节序:如果需要将 QString 序列化为二进制数据并控制字节序,可以结合 QDataStream。
cpp 复制代码
QString str = "Hello";
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);

// 设置字节序(小端或大端)
stream.setByteOrder(QDataStream::LittleEndian); // 或 BigEndian

// 写入 QString(会以 UTF-16 格式存储,受 ByteOrder 影响)
stream << str;
  • 总结
    • 常见编码(UTF-8、Latin1):QString 转 QByteArray 无字节序问题,因为它们是按字节存储的。
    • UTF-16 编码:
    • 默认使用系统字节序(无 BOM)。
    • 通过 toUtf16(true) 可添加 BOM 明确字节序。
    • 手动处理或 QDataStream 可强制指定字节序。
    • 关键点:字节序仅在多字节数值(如 UTF-16 的 QChar)转换时需要关注,单字节编码(如 UTF-8)无需考虑。

示例代码(验证字节序)

cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include <QString>
#include <QSysInfo>

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    QString str = "A"; // Unicode 字符 'A' 的 UTF-16 编码为 0x0041

    // 默认 UTF-16 转换(无 BOM)
    QByteArray utf16Default = str.toUtf16();
    qDebug() << "Default UTF-16 (no BOM):" << utf16Default.toHex();
    // 系统是小端序时输出: "4100"(低字节在前)
    // 系统是大端序时输出: "0041"(高字节在前)

    // 带 BOM 的 UTF-16
    QByteArray utf16WithBom = str.toUtf16(true);
    qDebug() << "UTF-16 with BOM:" << utf16WithBom.toHex();
    // 小端序系统输出: "fffe4100"(BOM=FFFE,数据=4100)
    // 大端序系统输出: "feff0041"(BOM=FEFF,数据=0041)

    return a.exec();
}

通过运行此代码,可以观察不同系统下的字节序差异。

互动

qt-通信协议基础-固定长度-小端字节序补0x00指导

相关推荐
小羊没烦恼!16 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读17 小时前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
C语言小火车18 小时前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁18 小时前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
孙启超19 小时前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int19 小时前
深入理解C++系列(20)——C++11(下)
开发语言·c++
慧都小项19 小时前
当边缘AI上产线:QtitanDocking 如何让工业 HMI 实现多视图协同
人工智能·qt·ui·边缘计算·qt6.3
CoderYanger20 小时前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
伞伞悦读21 小时前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json
CCCCCCCCharlie21 小时前
Linux进程控制四大核心操作
linux·开发语言