Как эффективно преобразовать только один следующий символ из байтового массива UTF-8?

У меня есть этот код, который работает:

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

куда bp это QByteArray::const_pointer, а также ut максимальная ожидаемая длина кодированной точки Unicode в кодировке UTF-8. Затем я беру первый QChar c от QString qs, Похоже, что должен быть более эффективный способ получить только следующее QChar из байтового массива UTF-8 без необходимости преобразования произвольного количества QByteArray в QString а потом получаю только первое QChar,

РЕДАКТИРОВАТЬ Из комментариев ниже, ясно, что никто еще не понимает мой вопрос. Итак, я начну с некоторых основ. UTF-8 и UTF-16 - это две разные кодировки мирового стандарта Unicode. Наиболее распространенной и рекомендуемой кодировкой Unicode для передачи через Интернет и текстовыми файлами Unicode является UTF-8, в результате чего каждая кодовая точка Unicode использует от 1 до 4 байтов в кодировке UTF-8. UTF-16, с другой стороны, более удобен для обработки символов внутри программы. Поэтому подавляющее большинство программного обеспечения постоянно выполняет преобразование между этими двумя кодировками. QChar - это более удобное кодирование UTF-16 для всех кодовых точек Unicode от 0x00 до 0xffff, которое охватывает большинство языков и символов, определенных на данный момент и широко используемых. Суррогатные пары используются для более высоких значений кодовой точки Unicode. В настоящее время кажется, что суррогатные пары имеют ограниченную поддержку и не представляют интереса для меня в данном вопросе.

Когда вы читаете текстовый файл в QPlainTextEdit преобразование выполняется автоматически и за кадром. Чтение QString из QByteArray это также может быть сделано автоматически (при условии, что для вашей локали и настроек кодека установлены UTF-8), или они могут быть выполнены явно с помощью toUtf8() или fromUtf8(), как в моем коде выше.

Преобразование в другом направлении может быть эффективно сделано неявно (за кадром) или явно с помощью следующего кода:

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

или же

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

где ba это QByteArray а также si является QString::const_iterator, Они делают то же самое (при условии, что кодек установлен в UTF-8). Они оба преобразуют следующий (один) символ из QChar указал в пределах QString в результате чего добавляется один или несколько байтов в ba,

Все, что я пытаюсь сделать, это обратное преобразование только для одного символа за раз, эффективно. Внутренне это делается для каждого конвертируемого персонажа, и я уверен, что это делается очень эффективно.

Проблема с QString::fromUtf8(p,n) в том, что n количество байтов для обработки, а не количество символов для преобразования. Следовательно, вы должны учитывать наибольшее количество байтов, которое может быть 3 (или 4, если он фактически обрабатывает суррогатные пары). Поэтому, если вам нужен только следующий символ, вы должны быть готовы обработать несколько байтов, и они преобразуются, а затем отбрасываются, если результат QString с более чем одним персонажем.

Q: есть функция преобразования, которая делает этот один символ за один раз?

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, он будет возвращать пустую строку.

Как только это будет возможно, результирующая строка будет содержать один декодированный символ Юникода.

Этот цикл максимально эффективен, и запоминая индекс цикла, можно получить следующие символы таким же образом.

Другие вопросы по тегам