Вопрос

Как преобразовать строку 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?

Большое спасибо!

Это было полезно?

Решение

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

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

Более длинный ответ:

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

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

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

РЕДАКТИРОВАТЬ: Ответ на комментарий шашки:

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

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

Другие советы

Используйте функцию WideCharToMultiByte . Укажите CP_UTF8 для параметра CodePage .

CHAR buf[256]; // or whatever
WideCharToMultiByte(
  CP_UTF8, 
  0, 
  StringToConvert, // the string you have
  -1, // length of the string - set -1 to indicate it is null terminated
  buf, // output
  __countof(buf), // size of the buffer in bytes - if you leave it zero the return value is the length required for the output buffer
  NULL,    
  NULL
);

Кроме того, кодировкой по умолчанию для приложений Юникод в Windows является UTF-16LE, поэтому вам может не потребоваться выполнять какой-либо перевод и просто использовать вторую версию sqlite3_open16 .

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

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

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

" преобразование utf-32 в utf-8 или utf-16 "

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

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

sqlite3_open(CStringA(L"MyWideCharFileName"), ...);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top