2010-10-30 10 views
18

Cree que esto estaría disponible, pero me está costando encontrar una función de biblioteca simple que convierta una cadena C o C++ de ISO -8859-1 que codifica a UTF-8. Estoy leyendo datos que están en codificación ISO-8859-1 de 8 bits, pero necesito convertirlos a una cadena UTF-8 para utilizar en una base de datos SQLite y, finalmente, una aplicación de Android.Convierta cadenas ISO-8859-1 a UTF-8 en C/C++

Encontré un producto comercial, pero está más allá de mi presupuesto en este momento.

+3

Hay nada simple al respecto. Puede usar la biblioteca de ICU de código abierto. –

+3

Si tiene que hacerlo, el código más simple es pregenerar una tabla de los 128 caracteres (UTF-8) correspondientes a los caracteres 8859-1 con el bit superior establecido. Los otros 128 8859-1 caracteres no están modificados. De esta forma, su código no tiene que entender Unicode en absoluto. Además, tenga cuidado con la diferencia entre ISO-8859-1 y Windows CP-1252. Este último tiene algunos caracteres adicionales donde 8859-1 tiene espacios (puntos de código no utilizados).A menos que se suponga que debe validar que su entrada realmente es ISO-8859-1, no tiene sentido no aceptar CP-1252, porque * verá * que está mal etiquetada. –

+0

@Steve: dado que UTF-8 es de longitud variable (en este caso, 1 o 2 bytes por carácter), una tabla de búsqueda no es tan fácil de usar. Vea mi respuesta, que debería ser igual de rápida y mucho más simple. –

Respuesta

31

Si la codificación de origen se siempre ser ISO-8859-1, esto es trivial. He aquí un bucle:

unsigned char *in, *out; 
while (*in) 
    if (*in<128) *out++=*in++; 
    else *out++=0xc2+(*in>0xbf), *out++=(*in++&0x3f)+0x80; 

Por razones de seguridad es necesario asegurarse de que el búfer de salida es dos veces mayor que el buffer de entrada, o bien incluyen un límite de tamaño y comprobar que en la condición de bucle.

+1

Wow. ¡Esto es muy útil! No esperaba con ansias otro algoritmo de búsqueda de tablas. Ahora para ANSEL-to-UTF-8 ... – gordonwd

+8

Esto sin duda responde a la pregunta. Pero como dije en un comentario anterior, las personas * le enviarán CP-1252 mal etiquetado como ISO-8859-1. Los servidores web son el ejemplo que he tropezado que me convencieron del problema, pero también los editores de texto que dicen guardar como "Latin-1" cuando no lo son. Que "si la codificación de origen siempre será ISO-8859-1" es un "si" bastante grande, y podría ser difícil rastrear y eliminar al malhechor responsable. –

+0

@Steve: podría agregar un error 'else if (* en <192) goto;;' error-out al encontrar códigos de control ISO-8859-1 (que probablemente estén mal codificados en los caracteres de Windows-1252, y caracteres no útiles) de todas formas). –

3

El estándar C++ 03 no proporciona funciones para convertir directamente entre conjuntos de caracteres específicos.

Dependiendo de su sistema operativo, puede usar iconv() en Linux, MultiByteToWideChar() & Co. en Windows. Una biblioteca que proporciona un gran soporte para la conversión de cadenas es la biblioteca de la ICU que es de código abierto.

+0

> ** "** El estándar de C++ no proporciona funciones para convertir directamente conjuntos de caracteres –

0

ISO-8859-1 a UTF-8 implica nada más que el algoritmo de codificación porque ISO-8859-1 es un subconjunto de Unicode. Entonces ya tienes los puntos de código Unicode. Compruebe Wikipedia para el algoritmo.

Los aspectos de C++, que integra eso con iostreams, son mucho más difíciles.

Te sugiero que camines alrededor de esa montaña en lugar de intentar perforarla o escalarla, es decir, implementar un simple convertidor de cuerda a cuerda.

Saludos & HTH.,

+0

El algoritmo no es del todo trivial, especialmente cuando los programadores de principiante a intermedio utilizan erróneamente' char * 'donde' sin signo char * 'es necesario. No trivialidades más importantes están en la definición de UTF-8, específicamente que debe rechazar los puntos de código sustituto y los valores fuera de rango. Afortunadamente, estos no aparecerán en un codificador que solo necesite manejar la entrada ISO-8859-1, pero si usted escribe un codificador tan limitado, es probable que alguien termine por usarlo indebidamente para un rango de entrada más grande más tarde sin agregar ningún control. –

+0

@ MichałLeon: Unicode no es una codificación. Hay varias codificaciones diferentes de Unicode, incluidas UTF-8 y UTF-16. Los primeros 256 puntos de código de Unicode son los mismos que Latin 1 (a.k.a., ISO-8859-1). Nota: el énfasis no te hace menos en desacuerdo con un hecho trivial. La próxima vez, en lugar de gritar y declinar, considere simplemente verificar hechos, o simplemente pregunte por cualquier cosa que no entienda. –

+0

@Martin: el bloque de puntos de código Unicode 128 a 255 se llama ["suplemento Latin-1" de Unicode] (https://en.wikipedia.org/wiki/Latin-1_Supplement_ (Unicode_block)), porque es el lo mismo que Latin-1. Unicode es una extensión directa de Latin-1. Sus comentarios son una tontería absurda, el tipo de balbuceo tecnológico que puede influenciar a las personas no técnicas e indica trolling. Supongo que estás trolling. –

2

La gente de Unicode tiene algunas tablas que pueden ayudar si se enfrenta con Windows 1252 en lugar de con el verdadero ISO-8859-1. El definitivo parece ser this one que mapea cada punto de código en CP1252 a un punto de código en Unicode. Codificar el Unicode como UTF-8 es un ejercicio directo.

No sería difícil analizar esa tabla directamente y formar una tabla de búsqueda en tiempo de compilación.

7

a C++ yo uso esto:

std::string iso_8859_1_to_utf8(std::string &str) 
{ 
    string strOut; 
    for (std::string::iterator it = str.begin(); it != str.end(); ++it) 
    { 
     uint8_t ch = *it; 
     if (ch < 0x80) { 
      strOut.push_back(ch); 
     } 
     else { 
      strOut.push_back(0xc0 | ch >> 6); 
      strOut.push_back(0x80 | (ch & 0x3f)); 
     } 
    } 
    return strOut; 
}