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