如何有效地转换UTF-8字节数组中的下一个字符?

时间:2016-02-09 13:42:22

标签: c++ qt utf-8 qchar

我的代码有效:

QString qs = QString::fromUtf8(bp,ut).at(0);
QChar c(qs[0]);

其中bpQByteArray::const_pointerut是UTF-8编码的Unicode代码点的最大预期长度。 然后,我从QChar c抓取第一个QString qs。 似乎应该有一种更有效的方法来简单地从UTF-8字节数组中仅获取下一个QChar,而不必将QByteArray的任意数量转换为QString并且然后只获得第一个QChar

编辑从下面的评论中,很明显没有人理解我的问题。所以我将从一些基础知识开始。 UTF-8和UTF-16是世界标准Unicode的两种不同编码。通过Internet和Unicode文本文件传输的最常见和鼓励的Unicode编码是UTF-8,这导致每个Unicode代码点使用1到4个字节的UTF-8编码。另一方面,UTF-16更方便处理程序内的字符。因此绝大多数软件都在这两种编码之间进行转换。 QChar是从0x00到0xffff的所有Unicode代码点的更方便的UTF-16编码,它涵盖了迄今定义和常用的大多数语言和符号。代理对用于更高的Unicode代码点值。目前,代理人对似乎只有有限的支持,对我来说,就目前的问题而言,我并不感兴趣。

当您将文本文件读入QPlainTextEdit时,转换会自动完成并在幕后完成。从QString读取QByteArray也可以自动完成(前提是您的区域设置和编解码器设置为UTF-8设置),或者可以使用toUtf8()或fromUtf8()显式地完成它们。我上面的代码。

可以有效地(在幕后)或使用以下代码明确地完成另一个方向的转换:

    ba += *si; // Depends on the UTF-8 codec

    ba += QString(*si).toUtf8(); // UTF-8 explicitly

其中baQByteArraysiQString::const_iterator。这些完全相同(假设编解码器设置为UTF-8)。它们都会转换QChar中指向QString内的下一个(一个)字符,从而在ba中附加一个或多个字节。

我正在努力的是一次只有一个字符的逆转换,有效。在内部,这是为每个被转换的角色完成的,我确信它的效率非常高。

QString::fromUtf8(p,n)的问题是n是要处理的字节的数量,而不是要转换的字符的数量。因此,您必须允许最大可能为3的字节数(如果它实际处理了代理项对,则为4)。因此,如果您想要的只是下一个字符,那么您必须准备好处理几个字节,并且它们会被转换,然后如果结果是带有多个字符的QString则被丢弃。

问:是否有转换功能一次执行此一个字符

1 个答案:

答案 0 :(得分:1)

您想使用QTextDecoder

根据文件:

  

QTextDecoder类提供基于状态的解码器。   文本解码器使用特定的编解码器将文本从编码的文本格式转换为Unicode。   解码器将此格式的文本转换为Unicode,记住调用之间所需的任何状态。

重要的是。 QString和QTextCodec是无状态的,因此它们可以处理整个字符串,从头开始。

另一方面,

QTextDecoder允许您一次一个字节地处理字节缓冲区,在调用之间保持状态,以便调用者知道UTF-8序列是否仅被部分解码。

例如:

QTextDecoder decoder(QTextCodec::codecForName("UTF-8"));
QString result;
for (int i = 0; i < bytearray.size(); i++) {
     result = decoder.toUnicode(bytearray.constData() + i, 1);
     if (!result.isEmpty()) {
          break; // we got our character !
     }
}

这个循环背后的基本原理是,只要解码器无法解码完整的UTF-8字符,它就会返回一个空字符串。

一旦能够,结果字符串将包含一个解码的unicode字符。

这个循环尽可能高效,并且通过记忆循环索引,可以以相同的方式获得下一个字符。