【问题标题】:restore runtime unicode strings恢复运行时 unicode 字符串
【发布时间】:2011-11-18 14:14:24
【问题描述】:

我正在构建一个应用程序,它通过 tcp 接收带有编码 unicode 的运行时字符串,示例字符串为“\u7cfb\u8eca\u4e21\uff1a\u6771\u5317 ...”。我有以下内容,但不幸的是我只能在编译时从中受益,因为:不完整的通用字符名称 \u 因为它在编译时需要 4 个十六进制字符。

QString restoreUnicode(QString strText)
   {
      QRegExp rx("\\\\u([0-9a-z]){4}");
      return strText.replace(rx, QString::fromUtf8("\u\\1"));
   }

我正在寻找运行时的解决方案,我可以预见到分解这些字符串并进行一些操作以将“\u”分隔符之后的那些十六进制转换为基数 10,然后将它们传递给 QChar 的构造函数,但我'正在寻找一种更好的方法,如果存在的话,因为我非常担心这种方法所产生的时间复杂度,而且我不是专家。

有没有人有任何解决方案或提示。

【问题讨论】:

  • fromUtf8("\\u\\1") 有效吗?你的想法和这个尝试有同样的问题:const char razy[] = "lass"; crazy Foo { int a; bool b; };
  • 为什么不使用QDataStream 对通过套接字的数据进行编码/解码?
  • 我无法控制服务器,只是使用第三方数据流,因为它是 ascii 和在小场合嵌入 unicode 的混合体。我已经制定了一个效果很好的解决方案,将在 6 小时内发布您自己的问题计时器的答案在本网站上到期。

标签: c++ qt qstring qregexp


【解决方案1】:

您应该自己解码字符串。只需获取 Unicode 条目 (rx.indexIn(strText)),解析它 (int result; std::istringstream iss(s); if (!(iss>>std::hex>>result).fail()) ... 并将原始字符串 \\uXXXX 替换为 (wchar_t)result

【讨论】:

  • 我做了类似的事情,它运行良好,Unicode 的存在率很低,所以我希望我的解决方案不会带来麻烦的 CPU 使用率。当网站允许时,我将在 6 小时内发布解决方案。
【解决方案2】:

对于关闭和将来遇到此线程的任何人,这是我在优化这些变量的范围之前的初始解决方案。不是它的粉丝,但考虑到我无法控制的流中 unicode 和/或 ascii 的不可预测性(仅限客户端),它可以工作,虽然 Unicode 的存在率很低,但最好处理它而不是丑陋的 \u1234等等

QString restoreUnicode(QString strText)
{
    QRegExp rxUnicode("\\\\u([0-9a-z]){4}");

    bool bSuccessFlag;
    int iSafetyOffset = 0;
    int iNeedle = strText.indexOf(rxUnicode, iSafetyOffset);

    while (iNeedle != -1)
    {
        QChar cCodePoint(strText.mid(iNeedle + 2, 4).toInt(&bSuccessFlag, 16));

        if ( bSuccessFlag )
            strText = strText.replace(strText.mid(iNeedle, 6), QString(cCodePoint));
        else
            iSafetyOffset = iNeedle + 1; // hop over non code point to avoid lock

        iNeedle = strText.indexOf(rxUnicode, iSafetyOffset);
    }

    return strText;
}

【讨论】:

    【解决方案3】:
    #include <assert.h>
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <locale>
    #include <codecvt>          // C++11
    using namespace std;
    
    int main()
    {
        char const  data[]  = "\\u7cfb\\u8eca\\u4e21\\uff1a\\u6771\\u5317";
    
        istringstream   stream( data );
    
        wstring     ws;
        int         code;
        char        slashCh, uCh;
        while( stream >> slashCh >> uCh >> hex >> code )
        {
            assert( slashCh == '\\' && uCh == 'u' );
            ws += wchar_t( code );
        }
    
        cout << "Unicode code points:" << endl;
        for( auto it = ws.begin();  it != ws.end();  ++it )
        {
            cout << hex << 0 + *it << endl;
        }
        cout << endl;
    
        // The following is C++11 specific.
        cout << "UTF-8 encoding:" << endl;
        wstring_convert< codecvt_utf8< wchar_t > >  converter;
        string const bytes = converter.to_bytes( ws );
        for( auto it = bytes.begin();  it != bytes.end();  ++it )
        {
            cout << hex << 0 + (unsigned char)*it << ' ';
        }
        cout << endl;
    }
    

    【讨论】:

    • 流不完全是 unicode,因为正在进行的流中的字符串中可能有非 unicode 条目,但谢谢。
    猜你喜欢
    • 2020-03-27
    • 2017-06-25
    • 2021-05-09
    • 2014-11-26
    • 1970-01-01
    • 2011-12-21
    • 2015-03-25
    • 1970-01-01
    • 2020-02-14
    相关资源
    最近更新 更多