QString来unicode std :: string

时间:2014-04-03 13:56:06

标签: qt unicode encoding qstring

我知道有很多关于将QString转换为char*的信息,但我仍需要在这个问题上做一些澄清。

Qt提供QTextCodec来将QString(内部存储unicode中的字符)转换为QByteArray,允许我检索char*,表示某些非字符串中的字符串unicode编码。但是当我想要一个unicode QByteArray时,我该怎么办?

QTextCodec* codec = QTextCodec::codecForName("UTF-8");
QString qstr = codec->toUnicode("Юникод");
std::string stdstr(reinterpret_cast<const char*>(qstr.constData()), qstr.size() * 2 );  // * 2 since unicode character is twice longer than char
qDebug() << QString(reinterpret_cast<const QChar*>(stdstr.c_str()), stdstr.size() / 2); // same

上面的代码按照我的预期打印“Юникод”。但是我想知道这是否是到达char*的unicode QString的正确方法。特别是,reinterpret_cast和这种技术中的大小算术看起来非常难看。

3 个答案:

答案 0 :(得分:5)

以下内容适用于Qt 5. Qt 4的行为有所不同,实际上已被打破。

您需要选择:

  1. 您是想要8位宽std::string还是16位宽std::wstring,还是其他类型。

  2. 目标字符串中需要什么编码?

  3. 在内部,QString存储UTF-16编码数据,因此任何Unicode代码点都可以用一个或两个QChar来表示。

    常见情况:

    • 本地编码的8位std::string(如:系统区域设置):

      std::string(str.toLocal8Bit().constData())
      
    • UTF-8编码的8位std::string

      str.toStdString()
      

      这相当于:

      std::string(str.toUtf8().constData())
      
    • UTF-16或UCS-4编码std::wstring,分别为16位或32位宽。 Qt完成16位与32位编码的选择,以匹配平台宽度wchar_t

      str.toStdWString()
      
    • U ++或U32 C ++ 11字符串 - 从Qt 5.5开始:

      str.toStdU16String()
      str.toStdU32String()
      
    • UTF-16编码的16位std::u16string - 这个hack只需要到Qt 5.4:

      std::u16string(reinterpret_cast<const char16_t*>(str.constData()))
      

      此编码不包括字节顺序标记(BOM)。

    在转换之前,很容易将BOM添加到QString本身:

    QString src = ...;
    src.prepend(QChar::ByteOrderMark);
    #if QT_VERSION < QT_VERSION_CHECK(5,5,0)
    auto dst = std::u16string{reinterpret_cast<const char16_t*>(src.constData()),
                              src.size()};
    #else
    auto dst = src.toStdU16String();
    

    如果您希望字符串很大,则可以跳过一个副本:

    const QString src = ...;
    std::u16string dst;
    dst.reserve(src.size() + 2); // BOM + termination
    dst.append(char16_t(QChar::ByteOrderMark));
    dst.append(reinterpret_cast<const char16_t*>(src.constData()),
               src.size()+1);
    

    在这两种情况下,dst现在都可以移植到具有任何字节序的系统。

答案 1 :(得分:2)

使用此:

QString Widen(const std::string &stdStr)
{
    return QString::fromUtf8(stdStr.data(), stdStr.size());
}

std::string Narrow(const QString &qtStr)
{
    QByteArray utf8 = qtStr.toUtf8();
    return std::string(utf8.data(), utf8.size());
}

在所有情况下,你在std :: string中should have utf8。

答案 2 :(得分:0)

您可以使用以下方法从UTF-16编码的QString中获取QByteArray:

QTextCodec *codec = QTextCodec::codecForName("UTF-16");
QTextEncoder *encoderWithoutBom = codec->makeEncoder( QTextCodec::IgnoreHeader );
QByteArray array  = encoderWithoutBom->fromUnicode( str );

这样就可以忽略开头的unicode字节顺序标记(BOM)。

您可以将其转换为char *,如:

int dataSize=array.size();
char * data= new char[dataSize];
for(int i=0;i<dataSize;i++)
{
    data[i]=array[i];
}

或者简单地说:

char *data = array.data();