Как преобразовать строку Unicode в строку utf-8 или utf-16? - PullRequest
6 голосов
/ 11 ноября 2008

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

8 голосов
/ 11 ноября 2008

Используйте функцию 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
);

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

7 голосов
/ 11 ноября 2008

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

Преобразование не требуется, если вы используете строки Unicode, такие как CString или wstring. Используйте sqlite3_open16 (). Вам нужно будет убедиться, что вы передали указатель WCHAR (приведенный к void *. Кажется, хромает! Даже если эта библиотека кроссплатформенная, я думаю, они могли бы определить широкий тип символа, который зависит от платформы и менее недружелюбен 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, что на Win32 занимает 16 бит. На других платформах может отличаться.

Есть еще одна деталь, на которую вы могли бы обратить внимание: 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.

3 голосов
/ 11 ноября 2008

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

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

0 голосов
/ 23 августа 2014

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

sqlite3_open(CStringA(L"MyWideCharFileName"), ...);
0 голосов
/ 11 ноября 2008

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

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

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

...