does (w) ifstream admite diferentes codificaciones

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, por ejemplo, archivos ASCII, UTF-8 y UTF-16?

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

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

C ++ admite codificaciones de caracteres por medio de std::locale y facet std::codecvt . La idea general es que un objeto de locale describe los aspectos del sistema que pueden variar de una cultura a otra, de un idioma (humano) a otro. Estos aspectos se dividen en facet , que son argumentos de plantilla que definen cómo se construyen los objetos dependientes de la localización (incluidas las secuencias de E / S). Cuando lee desde un istream o escribe en un ostream , la escritura real de cada personaje se filtra a través de las facetas de la configuración regional. Las facetas cubren no solo la encoding 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, solo porque las instalaciones existan para hacer codificaciones no significa que la biblioteca estándar en realidad maneje 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 encoding) son difíciles, ya que wchar_t puede ser demasiado pequeño (destruyendo sus datos) o demasiado grande (desperdiciando espacio) y los comstackdores más comunes ( por ejemplo, Visual C ++ y Gnu C ++) difieren en cuán grande es su implementación. Por lo tanto, generalmente necesita encontrar bibliotecas externas para hacer la encoding real.

  • iconv generalmente reconoce que es correcto, pero los ejemplos de cómo vincularlo al mecanismo de C ++ son difíciles de encontrar.
  • jla3ep menciona libICU , que es muy minucioso, pero la API de C ++ no intenta jugar muy bien con el estándar (hasta donde puedo decir: puedes escanear los ejemplos para ver si puedes hacerlo mejor).

El ejemplo más sencillo que puedo encontrar que cubre todas las bases, es de la faceta codecvt UTF-8 de Boost , 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 requiere un poco más de excavación en la fuente para entenderlo (y no pretendo):

 typedef wchar_t ucs4_t; std::locale old_locale; std::locale utf8_locale(old_locale,new utf8_codecvt_facet); ... std::wifstream input_file("data.utf8"); input_file.imbue(utf8_locale); ucs4_t item = 0; while (ifs >> item) { ... } 

Para comprender más acerca de las configuraciones regionales y cómo usan las facetas (incluido codecvt ), consulte lo siguiente:

  • Nathan Myers tiene una explicación completa de los lugares y las facetas . Myers fue uno de los diseñadores del concepto de locale. Él tiene más documentación formal si quieres pasar por ella.
  • La implementación de la Biblioteca estándar de Apache (anteriormente RogueWave) tiene una lista completa de facetas .
  • El Capítulo 14 de Nicolai Josuttis ‘ The C ++ Standard Library está dedicado al tema.
  • Angelika Langer y Klaus Kreft’s Standard C ++ IOStreams and Locales dedican un libro completo.

ifstream no se preocupa por la encoding del archivo. Simplemente lee caracteres (bytes) del archivo. wifstream lee bytes anchos ( wchar_t ), pero aún no sabe nada sobre la encoding de archivos. wifstream es lo suficientemente bueno para UCS-2 – encoding 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 internacional para Unicode (ICU) es un conjunto maduro y portátil de bibliotecas C / C ++ y Java para soporte Unicode, internacionalización de software (I18N) y globalización (G11N), dando a las aplicaciones los mismos resultados en todas las plataformas.

ICU se lanza bajo una licencia no restringida de código abierto que es adecuada para usar tanto con software comercial como con otro software libre o de código abierto.

El diseño de la cadena de caracteres anchos y la secuencia de caracteres amplia 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 escribió una serie que ilustra cómo trabajar con diferentes tipos de secuencias / cadenas de caracteres anchos .