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

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript