Как преобразовать строку Unicode в строку utf-8 или utf-16?

Как преобразовать строку Unicode в строку utf-8 или utf-16? Мой проект VS2005 использует набор символов Unicode, а sqlite в cpp предоставляет

int sqlite3_open(
  const char *filename,   /* Database filename (UTF-8) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);
int sqlite3_open16(
  const void *filename,   /* Database filename (UTF-16) */
  sqlite3 **ppDb          /* OUT: SQLite db handle */
);

для открытия папки. Как преобразовать строку, CString или wstring в кодировку UTF-8 или UTF-16?

спасибо!

5 ответов


короткий ответ:

преобразование не требуется, если вы используете строки Unicode, такие как CString или wstring. Использовать sqlite3_open16(). Вам нужно будет убедиться, что вы передаете указатель WCHAR (casted to void *. Выглядит отстойно! Даже если этот lib является кросс-платформой, я думаю, они могли бы определить широкий тип char, который зависит от платформы и менее недружелюбен, чем void *) к API. Например, для CString:(void*)(LPCWSTR)strFilename

более подробный ответ:

у вас нет Строка Unicode, которую вы хотите преобразовать в UTF8 или UTF16. У вас есть строка Unicode, представленная в вашей программе с использованием данной кодировки: Unicode не является двоичным представлением как таковым. Кодировки говорите, как кодовые точки Unicode (числовые значения) представлены в памяти (двоичный макет числа). Utf8 и формате UTF16 являются наиболее широко используемыми кодировками. Но они очень разные.

когда проект VS говорит "кодировка Unicode", это фактически означает, что"символы кодируются как UTF16". Таким образом можно использовать sqlite3_open16 () напрямую. Преобразование не требуется. Символы хранятся в типе WCHAR (в отличие от char), который занимает 16 бит (Fallsback на стандартный тип C wchar_t, что занимает 16 бит на Win32. На других платформах все может быть иначе. Спасибо за исправление, шашки).

есть еще одна деталь, на которую вы можете обратить внимание: UTF16 существует в 2 вкусах: Big Endian и Little Endian. Это порядок байтов этих 16 бит. Функция прототип, который вы даете для UTF16, не говорит, какой заказ используется. Но вы довольно безопасно предполагаете, что sqlite использует ту же конечность, что и Windows (Little Endian IIRC. Я знаю порядок, но всегда имел проблемы с именами :-) ).

EDIT: ответ на комментарий шашками:

UTF16 использует 16 бит код подразделения. Под Win32 (и только на Win32), wchar_t используется для такого блока памяти. Фокус в том, что некоторые символы Unicode требуют последовательность из 2 таких 16-битных кодовых единиц. Их называют суррогатными парами.

таким же образом UTF8 представляет 1 символ, используя последовательность от 1 до 4 байт. Тем не менее UTF8 используются с char тип.


использовать так и widechartomultibyte


все строковые типы C++ являются нейтральными кодировками. Они просто останавливаются на ширине символа и не делают никаких дальнейших предположений. Wstring использует 16-разрядные символы в Windows, соответствующие примерно utf-16, но это все еще зависит от того, что вы храните в потоке. Wstring никоим образом не гарантирует, что данные, которые вы вводите в него, должны быть действительными utf16. Windows использует utf16, когда UNICODE определен, поэтому, скорее всего, ваши строки уже utf16, и вам не нужно это делать что угодно.

несколько других предложили использовать функцию WideCharToMultiByte, которая (одна из) способов(ы) для преобразования utf16 в utf8. Но поскольку sqlite может обрабатывать utf16, это не должно быть необходимо.


utf-8 и utf-16 являются кодировками символов "unicode". То, о чем вы, вероятно, говорите, это utf-32, который является кодировкой символов фиксированного размера. Может быть, ищет

"Convert utf-32 into utf-8 or utf-16"

предоставляет вам некоторые результаты или другие документы по этому вопросу.


самый простой способ сделать это-использовать CStringA. Класс CString является typedef для CStringA (версия ASCII) или CStringW (широкая версия char). Оба этих класса имеют конструкторы для преобразования строковых типов. Я обычно использую:

sqlite3_open(CStringA(L"MyWideCharFileName"), ...);