2009-08-13 16 views
12

Cuando leo un archivo de texto en una cadena de caracteres anchos (std :: wstring) usando un wifstream, ¿la implementación de flujo admite diferentes codificaciones, es decir, puede usarse para leer, p. ¿Archivos ASCII, UTF-8 y UTF-16?does (w) ifstream admite diferentes codificaciones

Si no, ¿qué tendría que hacer?

(tengo que leer todo el archivo, si eso hace la diferencia)

+2

cómo imbuir las secuencias con la configuración regional. http://stackoverflow.com/questions/207662/writing-utf16-to-file-in-binary-mode/208431#208431 –

Respuesta

21

C++ soporta codificaciones de caracteres por medio de std::locale y la faceta std::codecvt. La idea general es que un objeto locale describe los aspectos del sistema que pueden variar de cultura a cultura, idioma (humano) a idioma. Estos aspectos se dividen en facet s, que son argumentos de plantilla que definen cómo se construyen los objetos dependientes de la localización (incluidos los flujos de E/S). Cuando lee desde istream o escribe en ostream, la escritura real de cada personaje se filtra a través de las facetas de la configuración regional. Las facetas no solo cubren la codificación de tipos Unicode, sino también características tan variadas como la forma en que se escriben los números grandes (por ejemplo, con comas o puntos), la moneda, el tiempo, las mayúsculas y un montón de otros detalles.

Sin embargo, el hecho de que las instalaciones existan para hacer codificaciones no significa que la biblioteca estándar maneje realmente todas las codificaciones, ni hace que dicho código sea simple de hacer bien. Incluso cosas tan básicas como el tamaño del personaje que debería leer (y mucho menos la parte de codificación) son difíciles, ya que wchar_t puede ser demasiado pequeño (arruinando sus datos) o demasiado grande (desperdiciando espacio) y los compiladores más comunes (por ejemplo, Visual C++ y Gnu C++) do difieren en cuán grande es su implementación. Por lo tanto, generalmente necesita encontrar bibliotecas externas para hacer la codificación real.

  • iconv es generalmente reconocen que es correcta, pero los ejemplos de cómo unirse al mecanismo de C++ son difíciles de encontrar.
  • jla3ep mentionslibICU, que es muy completo pero el C++ API no trata de jugar muy bien con el estándar (Por lo que yo puedo decir:. Puede escanear el examples para ver si se puede hacer mejor)

El ejemplo más sencillo que puedo encontrar que cubre todas las bases, es de Boost UTF-8 codecvt facet, con un ejemplo que específicamente trata de codificar UTF-8 (UCS4) para su uso por flujos IO. Se ve así, aunque no sugiero simplemente copiarlo textualmente. Se necesita un poco más de la excavación en the source para entenderlo (y no pretenden):

typedef wchar_t ucs4_t; 

std::locale old_locale; 
std::locale utf8_locale(old_locale,new utf8_codecvt_facet<ucs4_t>); 

... 

std::wifstream input_file("data.utf8"); 
input_file.imbue(utf8_locale); 
ucs4_t item = 0; 
while (ifs >> item) { ... } 

Para entender más sobre lugares, y cómo utilizan las facetas (incluyendo codecvt), echar un vistazo a la siguiente :

+1

Buen resumen. Es posible que desee agregar http://www.amazon.com/dp/0201183951 a su lista de libros. Es el tratamiento más completo del problema que conozco. – sbi

+0

sbi: Se agregó el libro a la lista. Gracias por el buen enlace. – quark

1

El diseño de la cadena de caracteres anchos y flujo de caracteres de ancho es anterior a UTF-8, UTF-16 y Unicode. Si desea obtener información técnica, la cadena estándar y la transmisión estándar no operan necesariamente en ASCII (es solo que básicamente todas las computadoras usan ASCII, podría tener una máquina EBCDIC).

Raymond Chen una vez wrote a series illustrating how to work with different wide character stream/string types.

4

ifstream no le importa la codificación del archivo. Simplemente lee caracteres (bytes) del archivo. wifstream lee bytes anchos (wchar_t), pero aún no sabe nada sobre la codificación de archivos. wifstream es lo suficientemente bueno para UCS-2 - codificación de caracteres de longitud fija para Unicode (cada carácter representado con dos bytes).

Puede usar la biblioteca IBM ICU para tratar con archivos Unicode.

El Componente internacionales para Unicode (UCI) es un maduro conjunto, portátil de C/C++ y bibliotecas Java para el soporte Unicode, la internacionalización de software (i18n) y la globalización (G11N), dando aplicaciones de los mismos resultados en todas las plataformas .

La UCI se libera bajo una licencia de fuente abierta no restrictiva que es adecuada para usar tanto con software comercial como con otro software libre o de código abierto.

+1

Creo que es un poco más correcto decir que abstracts 'ifstream' sobre la codificación. Hace uso de ella a través de instalaciones de nivel inferior: configuraciones regionales (para C++ estándar) y funciones i18n específicas de sistema operativo o biblioteca. es decir, 'ifstream' puede no importarle, pero sí le importa cómo se llama en este caso. – quark

+3

'locales' no tiene nada que ver con las codificaciones de Unicode. Cuando configura la configuración regional, solo da una pista a 'iostream' cómo debería representar símbolos en la consola. Pero no puede detectar la codificación del * archivo *. Y es imposible distinguir ANSI de UTF-8 usando 'ifstream'. –

Cuestiones relacionadas