如何使用带有Latin-1回退的UTF-8解码QByteArray

时间:2014-09-17 19:33:14

标签: c++ qt utf-8 qstring

我有一个连接到IRC服务器的套接字。我想将收到的数据(QByteArray)转换为QString。因为在IRC上,不是每个人都使用UTF-8,我想尝试使用UTF-8解码QByteArray:

QString s = QString::fromUtf8(array);

问题是Qt默默地替换了#34;坏"字符并始终返回QString。我想"尝试"解码,如果它无法正确解码,则回退到latin-1解码。

我怎么能这样做?

1 个答案:

答案 0 :(得分:4)

不幸的是,它看起来不像Qt提供的解码例程允许配置无效序列的处理。

相反,您应该能够执行以下操作:

QString s = QString::fromUtf8(array);
if (s.toUtf8() != array) {
  s = QString::fromLatin1(array);
}

UTF-8和UTF-16之间的直接转换(即,没有标准化)应该是无损且完全可逆的。如果从UTF-16转换为UTF-8不会产生原始数据,那是因为原始数据无效UTF-8。

虽然在正常情况下不太可能,但其他编码中的文本恰好是有效的UTF-8,但在UTF-8中与正确的编码有不同的含义。此类文本将被检测为UTF-8,并且不会按预期显示。避免这种情况的唯一方法是事先了解正确的编码,例如:通过协议声明正确的编码。


另一个选择是使用std::wstring_convert,它是C ++ 11标准库的一部分。

#include <codecvt> // for codecvt_utf8_utf16
#include <locale>  // for wstring_convert

QByteArray array = ...

std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
QString s;
try {
  std::u16string s16 = converter.from_bytes(array.data(), array.size());

  s = QString::fromUtf16(s16.c_str());

} catch(...) {
  s = QString::fromLatin1(array);
}

请注意,fromUtf16char16_t的使用取决于this change,{{3}}可能未包含在您使用的Qt版本中。据推测,他们最终还会添加fromStdU16String()之类的内容,以便您可以说QString::fromStdU16String(s16),或者添加隐式转化,这样您就可以说s = s16;

另请注意,libstdc ++(gcc的默认标准库实现)尚未包含此转换工具。 Visual Studio 2010及更高版本拥有它,而libc ++拥有它。