2010-12-17 12 views
6

Tengo una función que requiere que pase un string UTF-8 apuntado por un char *, y tengo el puntero char en un solo byte cuerda. ¿Cómo puedo convertir la cadena a codificación UTF-8 en C++? ¿Hay algún código que pueda usar para hacer esto? Gracias!Cómo convertir un const char * de un solo byte a una codificación UTF-8

+7

¿Qué codificación es la cadena original? – ybungalobill

+0

La cadena se deriva de una llamada a readddir para leer la ruta y los nombres de los archivos en el sistema de archivos. Entonces, no sé qué codificación es. Pero supongo que no es diferente a hacer algo como esto: char * string = "Una cadena extraña como è". –

+0

las rutas en linux no imponen una codificación dada, la única regla es que no puede contener un /. Por lo tanto, cualquiera puede crear un nombre de archivo utilizando cualquier codificación, o incluso un nombre de archivo que esté codificado de manera ilegal en cualquier juego de caracteres determinado. Se podría adivinar que es ISO8859-1 y transformarlo con la función iconv(). – nos

Respuesta

2

Para convertir una cadena a una codificación de caracteres diferente, utilice cualquiera de las diversas bibliotecas de codificación de caracteres. Una opción popular es iconv (el estándar en la mayoría de los sistemas Linux).

Sin embargo, para hacer esto primero necesita averiguar la codificación de su entrada. Lamentablemente, no hay una solución general para esto. Si la entrada no especifica su codificación (como, por ejemplo, las páginas web generalmente lo hacen), tendrá que adivinar.

En cuanto a su pregunta: Usted escribe que obtiene la cadena de llamar al readdir en un sistema de archivos FAT32. No estoy seguro, pero creo que readdir devolverá los nombres de los archivos tal como están almacenados por el sistema de archivos.En el caso de FAT/FAT32:

  • Los nombres de archivo cortos se codifican en algunos DOS code page - la página de código depende de cómo los archivos donde escriben, no hay manera de saber a partir de sólo el sistema de archivos que yo sepa.
  • Los nombres largos de archivo están en UTF-16.

Si se utiliza el módulo de vfat núcleo de Linux estándar para acceder a la partición FAT32, usted debe obtener los nombres de archivo largos de readdir (a menos que un archivo sólo tiene un nombre 8.3). Estos se pueden decodificar como UTF-16. FAT32 almacena internamente los nombres de archivos largos en UTF-16. El controlador vfat los convertirá a la codificación dada por el parámetro de montaje iocharset= (creo que es la codificación predeterminada del sistema).

Información adicional:

Usted puede tener que jugar con las opciones de montaje y codepageiocharset (véase http://linux.die.net/man/8/mount) para obtener los nombres de archivo a la derecha en el volumen FAT32. Intente montar de manera que los nombres de archivo se muestren correctamente en una consola Linux, luego continúe. Hay alguna explicación más aquí: http://www.nslu2-linux.org/wiki/HowTo/MountFATFileSystems

+0

El último enlace resolvió mi problema específico. Al parecer, fue suficiente montar el dispositivo con los parámetros adecuados para que funcione correctamente. Marcó esta como la respuesta aceptada ya que resolvió mi situación específica y explica correctamente el caso general. Gracias a todos de todos modos! –

4

Asumiendo Linux, estás buscando iconv. Cuando abre el convertidor (iconv_open), pasa de y a codificación. Si pasa una cadena vacía como desde, se convertirá desde la configuración regional utilizada en su sistema que debe coincidir con el sistema de archivos.

En Windows, tiene casi lo mismo con MultiByteToWideChar donde pasa CP_ACP como la página de códigos. Pero en Windows simplemente puede llamar a la versión Unicode de las funciones para obtener Unicode inmediatamente y luego convertirlo a UTF-8 con WideCharToMultiByte y CP_UTF8.

1

Supongo que el bit superior se establece en la cadena de 1 byte, por lo que la función a la que se está transfiriendo está esperando que pase más de 1 byte.

Primero, imprima la cadena en hexadecimal.

decir

unsigned char* str = "your string"; 
for (int i = 0; i < strlen(str); i++) 
    printf("[%02x]", str[i]); 

Ahora tienen una lectura del artículo de Wikipedia sobre la codificación UTF-8, que lo explica muy bien.
http://en.wikipedia.org/wiki/UTF-8

UTF-8 es un ancho variable donde cada carácter puede ocupar de 1 a 4 bytes.

Por lo tanto, convierta el hex a binario y vea cuál es el punto de código.

es decir, si el primer byte comienza 11110 (en binario), entonces está esperando una cadena de 4 bytes. Como ascii es de 7 bits 0-127, el bit superior siempre es cero, por lo que solo debe haber 1 byte. Por cierto, los bytes que siguen al primer byte en un carácter ancho de una cadena UTF8 comenzarán "10 ..." para los bits superiores. Estos son los bytes de continuación ... de eso es de lo que se queja tu función ... es decir, los bytes de continuación faltan cuando se espera. Así que la cadena no es tan verdadera como creías que era.

Puede convertir utilizando como alguien sugirió iconv, o tal vez esta biblioteca http://utfcpp.sourceforge.net/

+0

Probé con la cadena "/ system/mnt/usb0/audio/07 Dracula Der Pfähler.mp3" y obtuve [2f] [73] [79] [73] [74] [65] [6d] [2f] [6d] [6e] [74] [2f] [75] [73] [62] [30] [2f] [61] [75] [64] [69] [6f] [2f] [30] [37 ] [20] [44] [72] [61] [63] [75] [6c] [61] [20] [44] [65] [72] [20] [50] [66] [e4] [ 68] [6c] [65] [72] [2e] [6d] [70] [33]. Parece bastante extraño ya que el personaje ä es parte del conjunto ASCII, por lo que debería estar bien. ¿Me equivoco? ¡Gracias! –

+0

@Luca - Sí, estás equivocado (lo siento). Los caracteres ASCII en inglés (menos de 0x80) son idénticos a sus equivalentes UTF-8. ä convertido a e4 que no es legal UTF-8. –

+0

¡Ah, lo entiendo! Ok, entonces UTF-8 no es compatible con versiones anteriores de ASCII extendido. Esto explica por qué noté el problema con 'è' y 'ä'. ¡Gracias! –

Cuestiones relacionadas