Pregunta

¿Cómo convertir una cadena Unicode en una cadena utf-8 o utf-16? Mi proyecto VS2005 está utilizando el conjunto de caracteres Unicode, mientras que sqlite en cpp proporciona

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 */
);

para abrir una carpeta. ¿Cómo puedo convertir string, CString o wstring en UTF-8 o UTF-16 charset?

¡Muchas gracias!

¿Fue útil?

Solución

Respuesta corta:

No se requiere conversión si utiliza cadenas Unicode como CString o wstring. Use sqlite3_open16 (). Tendrás que asegurarte de pasar un puntero WCHAR (arrojado a void * . Parece cojo! Incluso si esta lib es multiplataforma, supongo que podrían haber definido un tipo de carácter amplio que depende de la plataforma y es menos hostil que un void * ) para la API. Tal como para un CString: (void*)(LPCWSTR)strFilename

La respuesta más larga:

No tiene una cadena Unicode que desea convertir a UTF8 o UTF16. Tiene una cadena Unicode representada en su programa usando una codificación dada: Unicode no es una representación binaria per se. Las codificaciones indican cómo se representan los puntos de código Unicode (valores numéricos) en la memoria (diseño binario del número). UTF8 y UTF16 son las codificaciones más utilizadas. Sin embargo, son muy diferentes.

Cuando un proyecto VS dice "Conjunto de caracteres Unicode", en realidad significa que los caracteres están codificados como UTF16. Por lo tanto, puede usar sqlite3_open16 () directamente. No se requiere conversión. Los caracteres se almacenan en el tipo WCHAR (a diferencia de char ) que toma 16 bits (Fallsback en el tipo C estándar wchar_t , que toma 16 bits en Win32. Puede ser diferente en otros plataformas. Gracias por la corrección, Damas).

Hay un detalle más al que puede prestarle atención: UTF16 existe en 2 sabores: Big Endian y Little Endian. Ese es el orden de bytes de estos 16 bits. El prototipo de función que proporciona para UTF16 no dice qué orden se utiliza. Pero está bastante seguro asumiendo que sqlite usa la misma endianidad que Windows (Little Endian IIRC. Conozco el orden pero siempre he tenido problemas con los nombres :-)).

EDITAR: Respuesta al comentario de las Damas:

UTF16 utiliza unidades de código de 16 bits . En Win32 (y solo en Win32), se usa wchar_t para dicha unidad de almacenamiento. El truco es que algunos caracteres Unicode requieren una secuencia de 2 unidades de código de 16 bits. Se llaman parejas sustitutas.

De la misma manera, un UTF8 representa 1 carácter usando una secuencia de 1 a 4 bytes. Sin embargo, UTF8 se utilizan con el tipo char .

Otros consejos

Utilice la función WideCharToMultiByte . Especifique CP_UTF8 para el parámetro 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
);

Además, la codificación predeterminada para aplicaciones Unicode en Windows es UTF-16LE, por lo que es posible que no necesite realizar ninguna traducción y solo use la segunda versión sqlite3_open16 .

Todos los tipos de cadena de C ++ son charset neutral. Simplemente se conforman con el ancho de un carácter y no hacen más suposiciones. Un wstring usa caracteres de 16 bits en Windows, que corresponden aproximadamente a utf-16, pero aún depende de lo que almacene en el hilo. El wstring no exige de ninguna manera que los datos que ingrese sean válidos utf16. Sin embargo, Windows usa utf16 cuando UNICODE está definido, por lo que lo más probable es que sus cadenas ya sean utf16 y no necesite hacer nada.

Algunos otros han sugerido usar la función WideCharToMultiByte, que es (una de) las formas de convertir utf16 a utf8. Pero dado que sqlite puede manejar utf16, eso no debería ser necesario.

utf-8 y utf-16 son ambos "unicode" codificaciones de caracteres. De lo que probablemente hablas es de utf-32, que es una codificación de caracteres de tamaño fijo. Tal vez buscando

" Convertir utf-32 en utf-8 o utf-16 "

le proporciona algunos resultados u otros documentos sobre esto.

La forma más sencilla de hacer esto es usar CStringA. La clase CString es un typedef para CStringA (versión ASCII) o CStringW (versión wide char). Ambas clases tienen constructores para convertir tipos de cadenas. Normalmente uso:

sqlite3_open(CStringA(L"MyWideCharFileName"), ...);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top