2009-05-04 19 views
42

No imaginaría algo tan básico como abrir un archivo usando la biblioteca estándar de C++ para una aplicación de Windows era complicado ... pero parece ser así. Por Unicode aquí me refiero a UTF-8, pero puedo convertir a UTF-16 o lo que sea, el punto es obtener una instancia ofstream a partir de un nombre de archivo Unicode. Antes de hackear mi propia solución, ¿hay una ruta preferida aquí? Especialmente uno multiplataforma?¿Cómo abrir un std :: fstream (ofstream o ifstream) con un nombre de archivo unicode?

+0

que este es un [duplicado] (http://stackoverflow.com/questions/480849/windows-codepage-interactions-with-standard-cc-filenames) pregunta. Vea si alguna de las respuestas puede ayudar. –

+0

¿Por qué no utiliza tipos de datos como 'std :: wofstream'? ¡Note el ** w **! – sergiol

Respuesta

51

La biblioteca estándar de C++ no es compatible con Unicode. char y wchar_t no son necesarios para ser codificaciones Unicode.

En Windows, wchar_t es UTF-16, pero no hay soporte directo para UTF-8 nombres de archivo en la biblioteca estándar (el char tipo de datos no es Unicode en Windows)

Con MSVC (y por lo tanto el TEL Microsoft) , se proporciona un constructor para FileStreams que tiene un nombre de archivo const wchar_t*, lo que permite crear la corriente como:

wchar_t const name[] = L"filename.txt"; 
std::fstream file(name); 

sin embargo, esta sobrecarga no es especificado por el estándar de C++ 11 (lo único que garantiza la presencia de la char versión basada). Tampoco está presente en implementaciones alternativas de STL como libstdC++ de GCC para MinGW (-w64), a partir de la versión g ++ 4.8.x.

Tenga en cuenta que al igual que char en Windows no es UTF8, en otros OS'es wchar_t puede no ser UTF16. Entonces, en general, esto no es portátil. La apertura de una secuencia con un nombre de archivo wchar_t no está definida de acuerdo con la norma, y ​​la especificación del nombre de archivo en char s puede ser difícil porque la codificación utilizada por char varía entre OS 's.

+0

¿Qué quiere decir con "fstream está garantizado para aceptar ambos wchar_t ..."? No tengo acceso al estándar 98 oficial, pero no puedo encontrar la mención de un wchar_t * ctor para basic_fstream en n2857 (es decir, IIUC, el borrador actual de C++ 0x) –

+0

Hmm, parece que tiene razón . Me corresponde corregir – jalf

+0

@ Éric: de acuerdo, los constructores para basic_fstream se definen en 27.8.1.12 del estándar '03, y hay dos: no-args y char *.fstream es un basic_fstream , y no hay miembros adicionales definidos para esa especialización. –

3

Las versiones actuales de Visual C++ std :: basic_fstream tienen un método open() que toma un wchar_t * según http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx.

+0

¿Esto finalmente/teóricamente será portátil? –

+3

No todos los SO y sistemas de archivos admiten nombres de archivos Unicode, por lo que no serían portátiles. De lo que puedo deducir, el wchar_t * open() y el constructor en fstream son extensiones de Microsoft porque NTFS admite nombres de archivo Unicode. –

+3

o más bien, porque NTFS usa UTF16 para codificar nombres de archivo Unicode. Linux también admite nombres de archivo Unicode, pero usa UTF8, por lo que la versión normal de char * funciona allí – jalf

1

Utilice std::wofstream, std::wifstream y std::wfstream. Aceptan un nombre de archivo Unicode. El nombre del archivo tiene que ser wstring, una matriz de wchar_t s, o tiene que tener _T() macro, o el prefijo antes del texto.

+0

¿Podría proporcionar pruebas de que 'std :: wfstream' es' Unicode'? Hasta mi modesto conocimiento, simplemente usan 'wchar_t', que es un caracter ancho, usualmente' 16-bits'. Pero el contenido podría o no ser 'Unicode'. –

+0

Lo que quiero decir es que aceptan cadenas Unicode, lo que responde a la pregunta, ¿no? – Brackets

+0

En realidad, responde la mitad de la pregunta: digamos que tienes tu ruta de archivo UTF16 en tu wfstream (o UTF8 en tu flujo de datos). Windows no acepta Unicode y devolverá la "URL incorrecta" si tiene algunos caracteres especiales (por ejemplo, chino). –

0

Tenga una mirada en Boost.Nowide:

#include <boost/nowide/fstream.hpp> 
#include <boost/nowide/cout.hpp> 
using boost::nowide::ifstream; 
using boost::nowide::cout; 

// #include <fstream> 
// #include <iostream> 
// using std::ifstream; 
// using std::cout; 

#include <string> 

int main() { 
    ifstream f("UTF-8 (e.g. ß).txt"); 
    std::string line; 
    std::getline(f, line); 
    cout << "UTF-8 content: " << line; 
} 
Cuestiones relacionadas