2009-01-26 7 views
5

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 creer que esto es probablemente SHIFT_JIS y/o la página de códigos de Windows 932.Interacciones de página de códigos de Windows con nombres de archivo C/C++ estándar?

Me parece que lo que está sucediendo anteriormente es tanto fopen como ofstream :: abre los nombres de archivo aceptados utilizando 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 abre eso el trabajo se realiza en la configuración regional "C", mientras que los 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é cambió misteriosamente, ¿quizás un Service Pack de VS2005?) Y esperando reunir un conjunto completo de "mejores prácticas" para manejar nombres de archivo Unicode en portable Código C++

+0

Tal vez podría darle el período de tiempo cuando esto ocurrió. Windows ha cambiado mucho a lo largo de los años. –

+0

Buen punto. El cambio ocurrió en el último año. – Sol

Respuesta

0

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 NULL), 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.

+2

No, todos los sistemas de archivos nativos de Linux ignoran la codificación de caracteres (sin embargo, a algunos FS no nativos no les importa). Los nombres de archivo son cadenas de bytes y los únicos caracteres especiales son barra inclinada y nula. Las codificaciones deben ser manejadas por el shell. –

0

Es posible que deba establecer la configuración regional del subproceso en la configuración regional predeterminada del sistema. ver aquí para una posible razón de sus problemas: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100887

+0

Hmmm ... esto es interesante. Al mirar mi código, es posible que las aperturas que funcionan estén siempre en la configuración regional "C", mientras que las que fallan están en lo que sea que esté la máquina del usuario. Sin embargo, eso no es algo que haya cambiado recientemente en nuestro extremo. .. – Sol

+0

¿Has actualizado tu visual studio? Si es así, entonces ese es el cambio en su extremo. Si no, lamento haberme quedado sin ideas ... – Stefan

+0

No, Visual Studio 2005 en todas partes. – Sol

2

No estoy al tanto de cualquier manera portátil de uso de archivos Unicode utilizando las bibliotecas del sistema por defecto. Pero hay algunos marcos que proporcionan funciones portátiles, por ejemplo:

  • para C: glib utiliza nombres de archivo en UTF-8;
  • para C++: glibmm también usa nombres de archivos 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.

0

Mac OS X utiliza Unicode como su codificación de caracteres original.Los objetos de cadena básicos son CFString y NSString. Almacenan un conjunto de caracteres como Unicode.

3

Funciones como fopen o ofstream :: open toman el nombre del archivo como char *, pero eso 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 el sistema operativo) página de código).

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).

Esta es la forma de cambiar la página de códigos del sistema: http://www.mihai-nita.net/article.php?artID=20050611a

A la larga podría considerar mover a Unicode (y usando _wfopen, wofstream).

+0

Como he actualizado la pregunta, lo extraño aquí es que fopen funciona con la página de códigos, pero ofstream :: open no. Además, ¿_wfopen y wofstream son realmente portátiles? – Sol

+0

"Funciones como fopen o ofstream :: open toman el nombre del archivo como char *, pero eso se interpreta como estar en la página de códigos del sistema" - Lo siento, no lo creo. fopen y ofstream :: open son funciones en las bibliotecas C y C++, por lo que deben usar de forma predeterminada la configuración regional C. Si una aplicación desea que las funciones CRT utilicen una configuración regional de Windows, debe llamar a la función de configuración regional del CRT. –

+0

"Lo siento, no lo creo ... deben usar de forma predeterminada la configuración regional C." => Bueno, pruébalo! –

0

¿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 del nombre de archivo fstream es extraño: no utiliza la codificación predeterminada del sistema, la que obtiene con GetACP y se establece 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:

  1. convierta el código para utilizar Unicode en todas partes

  2. fstreams Nunca abiertos utilizando nombres de archivo de carácter estrechas, siempre convierten a ellos a Unicode utilizando la codificación por defecto del sistema usted mismo, use el nombre de archivo de caracteres anchos open/ctor

  3. Recupere la página de códigos usando GetACP(), luego haga un

setlocale juego:

setlocale (LC_ALL, ("." + lexical_cast<string> (GetACP())).c_str()) 
Cuestiones relacionadas