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指导

相关推荐
资生算法程序员_畅想家_剑魔2 小时前
Java常见技术分享-14-多线程安全-锁机制-常见的锁以及底层实现-synchronized
java·开发语言
江沉晚呤时2 小时前
构建智能代理的利器:深入解析 Microsoft Agent Framework
开发语言·c#
走粥2 小时前
JavaScript Promise
开发语言·前端·javascript
范纹杉想快点毕业2 小时前
C语言设计模式:从基础架构到高级并发系统(完整实现版)
c语言·开发语言·设计模式
先做个垃圾出来………2 小时前
Python测试桩工具
java·开发语言·python
行思理2 小时前
FastAdmin新手教程
java·开发语言·fastadmin
就叫飞六吧2 小时前
py脚本一键生成常见文件格式案例
开发语言·python
Tony Bai2 小时前
Go 性能分析的“新范式”:用关键路径分析破解高并发延迟谜题
开发语言·后端·golang
lly2024062 小时前
MySQL 创建数据库
开发语言