#qt #multibyte #qchar
#qt #многобайтовый #qchar
Вопрос:
У меня есть два буфера (примерных размеров):
char c[512];
QChar q[256];
Предполагается, что ‘c’ содержит многобайтовую символьную строку (UTF-8). Мне нужно преобразовать его в последовательность QChar и поместить ее в ‘q’.
Я думаю, хорошим примером того, что мне нужно, могла бы быть функция MultiByteToWideChar.
ВАЖНО: эта операция не должна включать никаких явных или неявных выделений памяти, за исключением, возможно, дополнительных выделений в стеке. Пожалуйста, не отвечайте, если вы не уверены, что означает вышесказанное.
Комментарии:
1. Добро пожаловать в StackOverflow! Ваш вопрос вызывает у меня вопрос (и, я думаю, у других тоже): «Почему нет выделения?» Это серьезно ограничивает использование любого Qt из-за использования Qt PIMPL в большинстве классов.
2. Кроме того, знаете ли вы кодек вашей многобайтовой строки? (Я думаю, это так из-за фиксированных размеров массива в соотношении 2: 1)
3. Привет, Мартин. Логичный вопрос. Речь здесь идет о фрагментации памяти и использовании при операциях с высокой частотой кадров. Поэтому PIMPL в данном конкретном случае является немного обременительным. Что касается кодеков — Qt справляется с этим вопросом (например, при создании QString из QByteArray или const char *) Я не хочу ничего другого. Просто внешние заполнители. Windows API предоставляет такие функции, которые преобразуют широкий символ в многобайтовые строки и наоборот. Почему Qt этого не делает? (Или так ли это?)
4. Позволю себе не согласиться — Qt интерпретирует const char * как UTF-8, за исключением случаев, когда вы явно указываете иное. Ваш массив символов может содержать 512 символов. В UTF-8 это будет до 512 QChars.
5. Под «многобайтовой» вы, вероятно, имеете в виду текущую кодовую страницу ansi в Windows, не так ли? (большинство из них на самом деле являются однобайтовыми :)) Похоже, что не все знают этот термин, возможно, было бы лучше уточнить его в вопросе.
Ответ №1:
QChar
содержит ushort
единственный элемент as, поэтому его размер sizeof(ushort)
.
В QString
контексте он представляет «символы» UTF-16 (кодовые точки).
Итак, здесь все дело в кодировании.
Если вы знаете, что ваши данные в char const *
формате UTF-16 имеют тот же порядок байтов, что и в вашей системе, просто скопируйте их:
memcpy(q, c, 512);
Если вы хотите инициализировать a QString
своими const char *
данными, вы могли бы просто интерпретировать его как UTF-16, используя QString::fromRawData()
:
QString strFromData = QString::fromRawData(reinterpret_cast<QChar*>(c), 256);
// where 256 is sizeof(c) * sizeof(char) / sizeof(QChar)
Тогда вам даже не нужен QChar q[256]
массив.
Если вы знаете, что ваши данные имеют формат UTF-8, вам следует использовать QString::fromUtf8()
, а затем просто получить доступ к его внутренней памяти с помощью QString::constData()
.
Используя QString
с UTF-8, я не знаю ни одного метода, полностью предотвращающего выделение кучи. Но упомянутый способ должен выделяться только дважды: один раз для PIMPL QString
, один раз для строковых данных UTF-16.
Если ваши входные данные закодированы как UTF-8
, ответ Нет: вы не можете преобразовать их с помощью Qt.
Доказательство: просмотр исходного кода qtbase/src/corelib/codecs/qutfcodec.cpp мы видим, что все функции для кодирования / декодирования создают новые QString
/ QByteArray
экземпляры. Ни одна функция не работает с двумя массивами, как в вашем вопросе.
Комментарии:
1. Спасибо, Мартин. Это было бы просто. Как насчет UTF-8? Я думаю, хорошим примером того, что мне нужно, может быть MultiByteToWideChar ( learn.microsoft.com/en-us/windows/desktop/api/stringapiset /… )
2. Спасибо, Мартин. Я предполагаю, что это означает «нет, нет никакого способа сделать это».
3. Даже при использовании
MultiByteToWideChar
вам необходимо указать кодировку.4. Я считаю, что либо ваши ограничения слишком жесткие, либо Qt — неподходящий инструмент для этой работы. Вероятно, вы могли бы выполнить преобразование с помощью Qt, не выделяя строки в куче, например, с помощью
QTextStream
, но вам понадобитсяQTextCodec
, и это будет создано в куче снова.