Cómo generar cadenas Unicode en la consola de Windows
Ya hay algunas preguntas relacionadas con este problema. Creo que mi pregunta es un poco diferente porque no tengo un problema real, solo pregunto por interés académico. Sé que la implementación de Windows de UTF-16 es a veces contradictoria con el estándar Unicode (por ejemplo, intercalación) o más cercana a la antigua UCS-2 que a UTF-16, pero mantendré la terminología "UTF-16" aquí por razones de sencillez.
Antecedentes: en Windows, todo es UTF-16. Independientemente de si está tratando con el núcleo, el subsistema de gráficos, el sistema de archivos o lo que sea, está pasando cadenas UTF-16. No hay locales o conjuntos de caracteres en el sentido de Unix. Para la compatibilidad con las versiones medievales de Windows, hay una cosa llamada "páginas de códigos" que está obsoleta pero no obstante soportada. AFAIK, solo hay una función correcta y no obsoleta para escribir cadenas en la consola, a saberWriteConsoleW
, que toma una cadena UTF-16. Además, una discusión similar se aplica a las secuencias de entrada, que también ignoraré.
Sin embargo, creo que esto representa una falla de diseño en la API de Windows: hay una función genérica que se puede usar para escribir en todos los objetos de flujo (archivos, tuberías, consolas ...) llamadaWriteFile
, pero esta función está orientada a bytes y no acepta cadenas UTF-16. La documentación sugiere usarWriteConsoleW
para la salida de la consola, que está orientada al texto, yWriteFile
para todo lo demás, que está orientado a bytes. Dado que tanto las secuencias de consola como los objetos de archivo están representados por identificadores de objetos del núcleo y las secuencias de consola se pueden redirigir, debe llamar a una función para cada escritura en una secuencia de salida estándar que verifique si el identificador representa una secuencia de consola o un archivo, rompiendo la polimorfia. OTOH, creo que la separación de Windows entre cadenas de texto y bytes sin formato (que se refleja en muchos otros sistemas como Java o Python) es conceptualmente superior a la de Unixchar*
enfoque que ignora las codificaciones y no distingue entre cadenas y matrices de bytes.
Entonces mis preguntas son: ¿Qué hacer en esta situación? ¿Y por qué no se resuelve este problema incluso en las propias bibliotecas de Microsoft? Tanto .NET Framework como las bibliotecas C y C ++ parecen adherirse al modelo de página de códigos obsoleto. ¿Cómo diseñaría la API de Windows o un marco de aplicación para evitar este problema?
Creo que el problema general (que no es fácil de resolver) es que todas las bibliotecas suponen que todas las secuencias están orientadas a bytes e implementan secuencias orientadas a texto además de eso. Sin embargo, vemos que Windows tiene secuencias especiales orientadas a texto en el nivel del sistema operativo, y las bibliotecas no pueden lidiar con esto. En cualquier caso, debemos introducir cambios significativos en todas las bibliotecas estándar. Una forma rápida y sucia sería tratar la consola como una secuencia especial orientada a bytes que acepta solo una codificación. Esto aún requiere que las bibliotecas estándar C y C ++ se eluden porque no implementanWriteFile
/WriteConsoleW
cambiar. ¿Es eso correcto?