【问题标题】:Converting QString to utf16 hex representation for non ascii characters将 QString 转换为非 ascii 字符的 utf16 十六进制表示
【发布时间】:2016-12-14 08:17:57
【问题描述】:

我要将 QString 转换为其十六进制表示,一切正常,直到我输入一些特殊字符,如“€”:

QString l_str = "How are you";
qDebug() << "hex:     " << l_str.toUtf8().toHex();
qDebug() << "readable:" << l_str.toUtf8();

打印出来:

十六进制:“486f772061726520796f753f”

可读:“你好吗?”

因此很容易将十六进制值转换回 ascii,只是两个值(48 = H 等)ascii 字符的十六进制表示,它足以迭代和转换每两个字符。

如果我设置 l_str = "H€w ar€ you?",而 utf8 中的 hex € 符号是 "e282ac" 是 6 个值,结果如下:

十六进制:“48e282ac77206172e282ac20796f753f”

但是我怎样才能把它恢复成可读的字符串呢?

最好是转换成 utf16 字符串:

十六进制:“0048006F20AC00200061007220AC00200079006F0075003F”

考虑到“Ho€ ar€ you”字符串是在运行时创建的(所以没有可用的 QStringLiteral),我不能使用 auto 关键字。

【问题讨论】:

  • “将其恢复为可读字符串”究竟是什么意思?你怎么读字符串?
  • 我从 Web 服务器读取“ho€ ar€ you”,然后我必须将其转换为 utf16 十六进制数组,将其发送到我必须将其转换回“ho€ ar”的设备欧元你”。
  • 其中哪一个步骤失败了?
  • 邮票没问题,我只是无法从十六进制 = 48e282ac77206172e282ac20796f753f 中取回原始字符串
  • Web 服务器提供 bytes,其中 Content-Type 标头指定 byte 编码。因此,如果您收到带有 Content-Type: text/plain; charset=utf-8 之类的 HTTP 正文,那么您将知道这些字节是 UTF-8 并且可以使用 QString::fromUtf8() 将它们解码为 QString。一旦你有了一个QString,你就可以使用QString::utf16()从中得到一个UTF-16数组。要将 UTF-16 解码回QString,您可以使用QString::fromUtf16()

标签: string qt unicode hex ascii


【解决方案1】:

您可以将字符串转换为 utf8/16,然后将保存它的缓冲区转换为十六进制表示。可以按照相反的顺序执行这些步骤,从 hex 到 utf8/16 再到一个字符串。

toUtf16Hex 函数会在前面添加一个字节顺序标记,以便小端和大端主机都能正确解码 Utf16 表示。

// https://github.com/KubaO/stackoverflown/tree/master/questions/str-to-utf-38831190
#include <QtCore>

QByteArray toUtf8Hex(const QString & str) {
   return str.toUtf8().toHex();
}
QString fromUtf8Hex(const QByteArray & hex) {
   return QString::fromUtf8(QByteArray::fromHex(hex));
}

QByteArray toUtf16Hex(QString str) {
   str.prepend(QChar::ByteOrderMark);
   // It is OK to use `fromRawData` since toHex copies it.
   return QByteArray::fromRawData(
            reinterpret_cast<const char*>(str.constData()), (str.size()+1)*2).toHex();
}
QString fromUtf16Hex(const QByteArray & hex) {
   const QByteArray utf16 = QByteArray::fromHex(hex);
   return QString::fromUtf16(reinterpret_cast<const quint16*>(utf16.data()));
}

int main() {
   const QString str = QStringLiteral("H€w ar€ you?");

   // To Utf8 and back
   const QByteArray hex8 = toUtf8Hex(str);
   Q_ASSERT(fromUtf8Hex(hex8) == str);

   // To Utf16 and back
   const QByteArray hex16 = toUtf16Hex(str);
   Q_ASSERT(fromUtf16Hex(hex16) == str);
}

【讨论】:

    【解决方案2】:

    我找到了一个老套但可行的解决方案:

    QString l_str = "Ho€ Ar€ you?";
    qDebug() << "hex:     " << l_str.toUtf8().toHex();
    qDebug() << "readable:" << l_str.toUtf8();
    
    QTextCodec* l_codec = QTextCodec::codecForName("UTF-16");
    
    QByteArray l_string = l_codec->fromUnicode(l_str).toHex();
    qDebug() << "utf16 encoded: " << l_string;
    
    QByteArray l_reversed;
    
    for(int i=0; i < l_string.length(); i=i+4)
    {
        QString l_hex_chars_1 = l_string.mid(i, 2);
        QString l_hex_chars_2 = l_string.mid(i+2, 2);
        l_reversed.append(l_hex_chars_2);
        l_reversed.append(l_hex_chars_1);
    }
    
    QByteArray l_bom("feff");
    if(l_reversed.startsWith(l_bom))
    {
        l_reversed.remove(0, l_bom.length());
    }
    
    QString l_res;
    
    for(int i=0; i < l_reversed.length(); i=i+4)
    {
        QString l_hex_chars_1 = l_reversed.mid(i, 2);
        QString l_hex_chars_2 = l_reversed.mid(i+2, 2);
    
        int l_val = l_hex_chars_1.toInt(0,16)*256+l_hex_chars_2.toInt(0,16);
        QChar l_char(l_val);
        l_res.append(l_char);
    }
    qDebug() << "back to string: " << l_res;
    

    打印出来:

    十六进制:“48e282ac77206172e282ac20796f753f”

    可读:“你呢?”

    utf16 编码:“fffe4800ac207700200061007200ac20200079006f0075003f00”

    字节反转:“004820ac007700200061007220ac00200079006f0075003f”

    返回字符串:“你是你吗?”

    【讨论】:

    • utf16 字节顺序标记在那里,以便解码器可以在必要时进行字节交换。你不应该自己交换任何东西。您也不需要构建编解码器来获取字符串的 utf-16 表示:您可以使用 QString::utf16() 获得一个。您可以手动添加QChar::ByteOrderMark
    猜你喜欢
    • 1970-01-01
    • 2011-11-21
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 1970-01-01
    相关资源
    最近更新 更多