Come aprire uno std :: fstream (ofstream o ifstream) con un nome file unicode?
Domanda
Non immagineresti qualcosa di semplice come aprire un file usando la libreria standard C ++ per un'applicazione Windows era complicato ... ma sembra che lo sia. Con Unicode qui intendo UTF-8, ma posso convertirlo in UTF-16 o qualsiasi altra cosa, il punto è ottenere un'istanza ofstream da un nome file Unicode. Prima di hackerare la mia soluzione, c'è un percorso preferito qui? Soprattutto multipiattaforma?
Soluzione
La libreria standard C ++ non è compatibile con Unicode. char
e wchar_t
non devono essere codifiche Unicode.
Su Windows, wchar_t
è UTF-16, ma non esiste un supporto diretto per i nomi di file UTF-8 nella libreria standard (il tipo di dati char
non è Unicode su Windows)
Con MSVC (e quindi Microsoft STL), viene fornito un costruttore per filestreams che prende un const wchar_t *
, permettendoti di creare lo stream come:
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
Tuttavia, questo sovraccarico non è specificato dallo standard C ++ 11 (garantisce solo la presenza della versione basata su char
). Inoltre non è presente su implementazioni STL alternative come libstdc ++ di GCC per MinGW (-w64), a partire dalla versione g ++ 4.8.x.
Nota che, proprio come char
su Windows non è UTF8, su wchar_t
non è definito secondo lo standard e specificare il nome del file in char
può essere difficile perché la codifica utilizzata da char varia tra SO ' es.
Altri suggerimenti
Le versioni correnti di Visual C ++ the std :: basic_fstream hanno un metodo open ()
che accetta un wchar_t * secondo http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx .
A partire da C ++ 17, esiste un modo multipiattaforma per aprire uno std :: fstream con un nome file Unicode usando std :: filesystem :: path sovraccarico. Fino a C ++ 20, è possibile creare un percorso da una stringa UTF-8 con std :: filesystem :: u8path . Esempio:
std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
Dopo C ++ 20, puoi creare un percorso passando UTF-8 al costruttore: std :: filesystem :: path (u8 " ? ? ? ? ? ")
(u8path sarà deprecato) .
Usa std :: wofstream
, std :: wifstream
e std :: wfstream
. Accettano il nome file unicode. Il nome del file deve essere wstring
, array di wchar_t
, oppure deve avere la macro _T ()
o il prefisso L
prima del testo.
Dai un'occhiata a 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;
}
Se stai usando Qt mescolato con std :: ifstream
:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));