tutorial - Interacciones de Windows Codepage con nombres de archivo estándar C/C++?
programa en dev c++ para una tienda (6)
Un cliente se queja de que nuestro código solía escribir archivos con caracteres japoneses en el nombre del archivo, pero ya no funciona en todos los casos. Siempre hemos utilizado buenas cadenas de caracteres * para representar nombres de archivos, por lo que me sorprendió un poco que alguna vez funcionó, y no hemos hecho nada de lo que sea consciente que debería haber hecho que dejara de funcionar. Les pedí que me enviaran un archivo con un nombre de archivo incrustado exportado desde nuestro software, y parece que las cadenas usan caracteres hexadecimales 82 y 83 como el primer carácter de una secuencia de doble byte para representar los caracteres japoneses. Buscar en línea me lleva a pensar que probablemente sea SHIFT_JIS y / o la página de códigos de Windows 932.
Me parece que lo que está sucediendo anteriormente es tanto fopen como ofstream :: abre los nombres de archivo aceptados usando esta página de códigos; ahora solo fopen lo hace. He revisado los documentos forales de Visual Studio y no veo ninguna pista sobre qué hace que una cadena aceptable pase para abrirse.
En el corto plazo, espero que alguien pueda arrojar algo de luz sobre el problema específico de Windows fopen versus ofstream :: open para mí. A la larga, realmente me gustaría saber la forma aceptada de abrir nombres de archivo Unicode (¿y otros?) En C ++, en Windows, Linux y OS X.
Editado para agregar: creo que las aperturas de ese trabajo se realizan en la configuración regional "C", mientras que las que no funcionan se realizan en la configuración regional predeterminada del cliente. Sin embargo, ese ha sido el caso desde hace años, y la versión anterior del programa todavía funciona hoy en su sistema, por lo que parece una apuesta arriesgada para explicar el problema que estamos viendo.
Actualización: envié un pequeño programa de prueba al cliente. Se ha verificado que fopen funciona bien con el nombre de archivo SHIFT_JIS, y std :: ofstream no. Esto está en Visual Studio 2005 y sucedió independientemente de si utilicé la configuración regional predeterminada o la configuración regional "C".
Todavía estoy interesado si alguien tiene una explicación para este comportamiento (y por qué ha cambiado misteriosamente, ¿quizás un service pack de VS2005?) Y espero reunir un conjunto completo de "mejores prácticas" para manejar nombres de archivos Unicode en código portátil C ++.
Es posible que deba establecer la configuración regional del subproceso en la configuración regional predeterminada del sistema. Consulte aquí un posible motivo para sus problemas: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100887
Estoy casi seguro de que en Linux, la cadena de nombre de archivo es una cadena UTF-8 (en el sistema de archivos EXT3, por ejemplo, los únicos caracteres no permitidos son barras y NULOS), almacenados en un char *
normal. La página man no parece mencionar la codificación de caracteres, que es lo que me lleva a creer que es el estándar del sistema de UTF-8. OS X probablemente use lo mismo, ya que proviene de raíces similares, pero estoy menos seguro de esto.
No conozco ninguna forma portátil de usar archivos Unicode usando bibliotecas de sistema predeterminadas. Pero hay algunos marcos que proporcionan funciones portátiles, por ejemplo:
- para C: glib usa nombres de archivo en UTF-8;
- para C ++: glibmm también usa nombres de archivo en UTF-8, requiere glib;
- para C ++: boost puede usar wstring para nombres de archivos.
Estoy bastante seguro de que los frameworks .NET / mono también contienen funciones de sistema de archivos portátiles, pero no los conozco.
Mac OS X usa Unicode como su codificación de caracteres nativa. Los objetos de cadena básicos son CFString y NSString. Almacenan un conjunto de caracteres como Unicode.
Las funciones como fopen o ofstream :: open toman el nombre del archivo como char *, pero se interpreta como que está en la página de códigos del sistema.
Significa que puede ser un carácter japonés representado como Shift-JIS (cp932), o chino simplificado (Big 5 / cp936), coreano, árabe, ruso, lo que sea (siempre que coincida con la página de códigos del sistema operativo).
También significa que puede usar nombres de archivos japoneses solo en un sistema japonés. Cambie la página de códigos del sistema y la aplicación "deja de funcionar". Sospecho que esto es lo que sucede aquí (no hay grandes cambios en Windows desde Win 2000, en esta área).
Así es como cambia la página de códigos del sistema: http://www.mihai-nita.net/article.php?artID=20050611a
A largo plazo, podría considerar pasar a Unicode (y usar _wfopen, wofstream).
Alguien sigue viendo esto? Acabo de investigar esta pregunta y no encontré respuestas en ningún lado, así que puedo tratar de explicar mis hallazgos aquí.
En VS2005, el manejo de los archivos de fstream es extraño: no usa la codificación predeterminada del sistema, la que obtiene con GetACP y configurada en el Panel de control / Región e Idioma / Administrativo. Pero siempre CP 1252 - Creo.
Esto puede causar una gran confusión, y Microsoft ha eliminado esta peculiaridad en versiones VS posteriores.
Todas las soluciones para VS2005 tienen sus inconvenientes:
Convierte tu código para usar Unicode en todos lados
Nunca abra fstreams utilizando nombres de archivo de caracteres angostos, siempre conviértelos a Unicode utilizando la codificación predeterminada del sistema usted mismo, utilice el nombre de archivo de caracteres anchos open / ctor
Recupere la página de códigos con GetACP (), luego haga una
setlocale coincidente:
setlocale (LC_ALL, ("." + lexical_cast<string> (GetACP())).c_str())