c - UTF-8 en Windows
winapi unicode (4)
¿Cómo configuro la página de códigos para UTF-8 en un programa C de Windows?
Tengo una biblioteca de terceros que tiene fopen para abrir archivos. Puedo usar wcstombs para convertir mis nombres de archivo Unicode a la página de códigos actual, sin embargo, si el usuario tiene un nombre de archivo con un carácter fuera de la página de códigos, se rompe.
Idealmente, simplemente llamaría a _setmbcp (65001) para configurar la página de códigos en UTF-8, sin embargo, la documentación de MSDN para _setmbcp indica que UTF-8 no es compatible.
¿Cómo puedo evitar esto?
Actualización 2018: Windows 10 ha hecho que la página de códigos "65001" sea menos "pseudo" en dos pasos:
- Cambios
conhost
: Windows Subsystem para Linux usa la página de códigos 65001 para sus consolas. También es posible ejecutarchcp 65001
encmd.exe
desde WSL. (Ha causado algunos errores bastante tontos de Python ). - escenario completo: Windows desde la compilación 17035 permite configurar UTF-8 como la página de códigos de configuración regional . Esto está disponible a partir de la actualización de abril de 2018.
Todas las API de Windows piensan en UTF-16, por lo que es mejor escribir un contenedor alrededor de su biblioteca que se convierta en los límites.
Por extraño que parezca, Windows piensa que UTF-8 es una página de códigos con el propósito de la conversión, por lo que debes usar las mismas API que usarías para convertir páginas de códigos:
std::wstring Utf8ToUtf16(const char* u8string)
{
int wcharcount = strlen(u8string);
wchar_t *tempWstr = new wchar_t[wcharcount];
MultiByteToWideChar(CP_UTF8, 0, u8string, -1, tempWstr, wcharcount);
wstring w(tempWstr);
delete [] tempWstr;
return w;
}
Y algo de forma similar a convertir de nuevo.
Utilice cygwin (que proporciona una configuración regional UTF-8 de forma predeterminada), o escriba su propio libc hack para Windows que _wfopen
traducciones necesarias UTF-8 a UTF-16 y _wfopen
funciones no estándar _wfopen
etc.
Desafortunadamente, no hay forma de hacer que Unicode sea la página de códigos actual en Windows. Las constantes CP_UTF7
y CP_UTF8
son pseudocódigos de páginas, que se usan solo en las funciones de conversión MultiByteToWideChar y WideCharToMultiByte , como mencionó Ben.
Tu problema es similar al de las clases de C ++ de fstream. Los constructores de fstream solo aceptan nombres char*
, lo que hace imposible abrir un archivo con un nombre Unicode verdadero. La única solución ofrecida por VC era un hack: abra el archivo por separado y luego establezca el manejador en el objeto de transmisión. Me temo que esta no es una opción para usted, por supuesto, ya que la biblioteca de terceros probablemente no acepte identificadores.
La única solución que se me ocurre es crear un archivo temporal con un nombre que no sea Unicode, que esté vinculado al original y usarlo como parámetro.