2010-06-05 26 views
8

recibo respuesta del servidor en utf-8 pero no puedo leer eso. cómo convertir utf-8 a ASCII en C++?cómo convertir utf-8 a ASCII en C++?

+5

¿Todos los caracteres son caracteres ASCII de un solo byte? – fmark

+0

no sé. Solo sé que la respuesta está en utf-8 – Suri

+0

¿Qué 'servidor' es esto? ¿Estás seguro de que los datos no están comprimidos o algo así? –

Respuesta

23

Primero tenga en cuenta que ASCII es un formato de 7 bits. Hay codificaciones de 8 bits, si buscas uno de estos (como ISO 8859-1) necesitarás ser más específico.

Para convertir una cadena ASCII a UTF-8, no hacer nada: son lo mismo. Entonces, si su cadena UTF-8 está compuesta por solo de caracteres ASCII, entonces ya es una cadena ASCII y no es necesaria ninguna conversión.

Si la cadena UTF-8 contiene caracteres no ASCII (cualquier cosa con acentos o caracteres no latinos), no hay forma de convertirlo a ASCII. (Quizás pueda convertirlo a una de las codificaciones ISO, quizás).

Hay maneras de quitar los acentos de los caracteres latinos para obtener al menos cierta semejanza en ASCII. Alternativamente, si solo desea eliminar los caracteres que no son ASCII, simplemente elimine todos los bytes con valores> = 128 desde la cadena utf-8.

0

UTF-8 es compatible con versiones anteriores de ASCII, lo que significa que todos los caracteres ASCII están codificados como valores de bytes únicos sin modificar en UTF-8. Si el texto debe ser ASCII pero no puede leerlo, debe haber otro problema.

4

UTF-8 es una codificación que puede asignar todos los caracteres Unicode. ASCII solo admite un subconjunto muy pequeño de Unicode.

Para el subconjunto de Unicode que es ASCII, la asignación de UTF-8 a ASCII es una asignación directa de bytes de uno a uno, por lo que si el servidor le envía un documento que solo contiene caracteres ASCII en codificación UTF-8 entonces puedes leerlo directamente como ASCII.

Si la respuesta contiene caracteres que no son ASCII, haga lo que haga, no podrá expresarlos en ASCII. Para filtrar estos de una secuencia UTF-8, puedes filtrar cualquier byte> = 128 (0x80 hex).

+0

"Para filtrar estos de una secuencia UTF-8 puedes filtrar cualquier byte> = 128 (0x80 hex)" Por supuesto , esto destruirá irrevocablemente tus datos. –

+0

@ Jörg W Mittag: Sí, lo hará, pero hubiera pensado que esto era obvio a partir de la descripción del proceso. –

+0

Es * debería * ser. Pero, por mi propia experiencia tratando de completar formularios en sitios web, puedo decirte: no lo es. Ayer mismo me di cuenta de que mi nombre fue destruido cuando eBay * Germany * transmitió mi nombre a * German * Postal Service. ¡Ya pues! –

4

Si la cadena contiene caracteres que no existen en ASCII, entonces no hay nada que puede hacer, porque, bueno, esos caracteres no existen en ASCII.

Si la cadena contiene sólo caracteres que do existen en ASCII, entonces no hay nada que necesidad que hacer, ya que la cadena es ya en la codificación ASCII: UTF-8 fue diseñado específicamente para sea ​​compatible con ASCII de manera tal que cualquier carácter que esté en ASCII tenga exactamente la misma codificación en UTF-8 que en ASCII, y que cualquier carácter que sea no en ASCII pueda nunca tenga una codificación que es válido ASCII, es decir, siempre tiene una codificación whi ch es ilegal en ASCII (específicamente, cualquier carácter no ASCII se codificará como una secuencia de 2 – 4 octetos, todos los cuales tienen su bit más significativo establecido, es decir, tienen un valor entero> 127).

En lugar de simplemente tratar de convertir la cadena, usted podría tratar de transliterate la cadena. La mayoría de los idiomas en este planeta tienen algún tipo de esquema de transliteración ASCII que al menos mantiene el texto algo comprensible. Por ejemplo, mi primer nombre es "Jörg" y su transcripción de ASCII sería "Joerg".El nombre del creador del lenguaje de programación de Ruby es "ま つ も and and and and and" y su transcripción de ASCII sería "Matsumoto Yukihiro". Sin embargo, tenga en cuenta que va a perder información. Por ejemplo, la sz-ligature alemana se transcribe a "ss", por lo que la palabra "Maße" (mediciones) se transcribe a "Masse". Sin embargo, "Masse" (masa, en el sentido del físico, no del cristiano) es también una palabra. Como otro ejemplo, el turco tiene 4 "i" s (pequeño y capital, con y sin punto) y ASCII solo tiene 2 (pequeño con punto y capital sin punto), por lo tanto, perderá información sobre el punto o si o no era una letra mayúscula.

Por lo tanto, la única manera que no pierda la información (en otras palabras: los datos corruptos), es de alguna manera codificar los caracteres no ASCII en secuencias de caracteres ASCII. Existen muchos esquemas de codificación populares: referencias de entidades SGML, MIME, secuencias de escape Unicode, Τ y Epsilon; Χ o La Τ & Epsilon; Χ. Por lo tanto, codificaría los datos al ingresar a su sistema y los decodificará cuando abandone el sistema.

Por supuesto, la forma más fácil sería simplemente arreglar su sistema.

0

ASCII es una página de códigos que representa 128 caracteres y códigos de control donde utf8 puede representar cualquier carácter en el estándar Unicode, que es mucho más que las capacidades ASCII. Así que la respuesta a su pregunta es: No es posible A menos que tenga más especificaciones para la fuente de datos.

9

Este ejemplo funciona bajo Windows (que no ha mencionado su sistema operativo de destino):

// The sample buffer contains "©ha®a©te®s" in UTF-8 
    unsigned char buffer[15] = { 0xc2, 0xa9, 0x68, 0x61, 0xc2, 0xae, 0x61, 0xc2, 0xa9, 0x74, 0x65, 0xc2, 0xae, 0x73, 0x00 }; 
    // utf8 is the pointer to your UTF-8 string 
    char* utf8 = (char*)buffer; 
    // convert multibyte UTF-8 to wide string UTF-16 
    int length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, NULL, 0); 
    if (length > 0) 
    { 
     wchar_t* wide = new wchar_t[length]; 
     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, wide, length); 

     // convert it to ANSI, use setlocale() to set your locale, if not set 
     size_t convertedChars = 0; 
     char* ansi = new char[length]; 
     wcstombs_s(&convertedChars, ansi, length, wide, _TRUNCATE); 
    } 

Recuerde delete[] wide; y/o ansi cuando ya no sean necesarios. Dado que esto es unicode, recomendaría mantener el wchar_t* en lugar de char* a menos que esté seguro de que el búfer de entrada contiene caracteres que pertenecen al mismo subconjunto ANSI.

+0

funcionó en Windows7 pero no funcionó en XP-Embedded. – ufukgun

+0

Probablemente porque XPEmbedded no viene con la página de códigos US-ASCII (20127) instalada por defecto. Nos encontramos con esto también. – CoreyStup

-3

En cuanto a la frase

"Si la cadena contiene caracteres que no existen en ASCII, entonces no hay nada que puede hacer, porque, bueno, esos personajes no existen en ASCII."

está mal.

UTF-8 es un conjunto de códigos multibyte y puede tomar más de 2 juegos de símbolos (idiomas). Prácticamente tienes un solo idioma (inglés como siempre) o 2 idiomas, uno de ellos es inglés.

  • Primer caso es simple ASCII char (cualquier codificación).
  • El segundo describe la codificación correspondiente de ASCII char. Si no es chino o árabe.

En las condiciones anteriores, puede convertir UTF-8 en caracteres ASCII. La función correspondiente no existe en C++. Entonces puedes hacerlo manualmente.Es fácil detectar símbolos de dos bytes de 1 byte. El bit alto del primer byte se establece para los de dos bytes y de lo contrario no se configura.

0

Tenga en cuenta que hay dos tipos: UTF8UTF8_with_BOM y UTF8_without_BOM. Y debe manejarlo de manera diferente en convertir a ANSI. Las siguientes funciones funcionarán.

  • UTF8_with_BOM a ANSI

    void change_encoding_from_UTF8_with_BOM_to_ANSI(const char* filename) 
    { 
        ifstream infile; 
        string strLine=""; 
        string strResult=""; 
        infile.open(filename); 
        if (infile) 
        { 
         // the first 3 bytes (ef bb bf) is UTF-8 header flags 
         // all the others are single byte ASCII code. 
         // should delete these 3 when output 
         getline(infile, strLine); 
         strResult += strLine.substr(3)+"\n"; 
    
         while(!infile.eof()) 
         { 
          getline(infile, strLine); 
          strResult += strLine+"\n"; 
         } 
        } 
        infile.close(); 
    
        char* changeTemp=new char[strResult.length()]; 
        strcpy(changeTemp, strResult.c_str()); 
        char* changeResult = change_encoding_from_UTF8_to_ANSI(changeTemp); 
        strResult=changeResult; 
    
        ofstream outfile; 
        outfile.open(filename); 
        outfile.write(strResult.c_str(),strResult.length()); 
        outfile.flush(); 
        outfile.close(); 
    } 
    
    // change a char's encoding from UTF8 to ANSI 
    char* change_encoding_from_UTF8_to_ANSI(char* szU8) 
    { 
        int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0); 
        wchar_t* wszString = new wchar_t[wcsLen + 1]; 
        ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen); 
        wszString[wcsLen] = '\0'; 
    
        int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0, NULL, NULL); 
        char* szAnsi = new char[ansiLen + 1]; 
        ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), szAnsi, ansiLen, NULL, NULL); 
        szAnsi[ansiLen] = '\0'; 
    
        return szAnsi; 
    } 
    
  • UTF8_without_BOM a ANSI

    void change_encoding_from_UTF8_without_BOM_to_ANSI(const char* filename) 
    { 
        ifstream infile; 
        string strLine=""; 
        string strResult=""; 
        infile.open(filename); 
        if (infile) 
        { 
         while(!infile.eof()) 
         { 
          getline(infile, strLine); 
          strResult += strLine+"\n"; 
         } 
        } 
        infile.close(); 
    
        char* changeTemp=new char[strResult.length()]; 
        strcpy(changeTemp, strResult.c_str()); 
        char* changeResult = change_encoding_from_UTF8_to_ANSI(changeTemp); 
        strResult=changeResult; 
    
        ofstream outfile; 
        outfile.open(filename); 
        outfile.write(strResult.c_str(),strResult.length()); 
        outfile.flush(); 
        outfile.close(); 
    } 
    
Cuestiones relacionadas