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 分钟前
Python Flask应用中文件处理与异常处理的实践指南
开发语言·python·flask
岁岁种桃花儿2 分钟前
CentOS7 彻底卸载所有JDK/JRE + 重新安装JDK8(实操完整版,解决kafka/jps报错)
java·开发语言·kafka
csbysj202015 分钟前
AngularJS 模块
开发语言
独好紫罗兰23 分钟前
对python的再认识-基于数据结构进行-a003-列表-排序
开发语言·数据结构·python
wuhen_n30 分钟前
JavaScript内置数据结构
开发语言·前端·javascript·数据结构
不会代码的小测试32 分钟前
UI自动化-POM封装
开发语言·python·selenium·自动化
roman_日积跬步-终至千里38 分钟前
【Java并发】Java 线程池实战:警惕使用CompletableFuture.supplyAsync
java·开发语言·网络
lsx20240644 分钟前
C++ 基本的输入输出
开发语言
mengzhi啊1 小时前
QUndoView 本质是一个 Qt 界面控件(继承自 QListView),专门适配 QUndoStack
qt
CodeSheep程序羊1 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展