Vous n'imagineriez pas quelque chose d'aussi fondamental que d'ouvrir un fichier à l'aide de la bibliothèque standard C++ pour une application Windows était délicat ... mais cela semble être le cas. Par Unicode ici, je veux dire UTF-8, mais je peux convertir en UTF-16 ou peu importe, le point consiste à obtenir une instance ofstream à partir d'un nom de fichier Unicode. Avant de pirater ma propre solution, existe-t-il un itinéraire préféré ici? Surtout un multi-plateforme?
La bibliothèque standard C++ n'est pas compatible avec Unicode. char
et wchar_t
ne sont pas obligatoirement des codages Unicode.
Sous Windows, wchar_t
correspond à UTF-16, mais les noms de fichiers UTF-8 ne sont pas directement pris en charge dans la bibliothèque standard (le type de données char
n'est pas Unicode sous Windows).
Avec MSVC (et donc le STL Microsoft), un constructeur pour filestreams est fourni qui prend un nom de fichier const wchar_t*
, ce qui vous permet de créer le flux en tant que:
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
Toutefois, cette surcharge n'est pas spécifiée par le standard C++ 11 (elle garantit uniquement la présence de la version à base char
). Il n'est également pas présent dans les implémentations STL alternatives telles que libstdc ++ de GCC pour MinGW (-w64), à partir de la version g ++ 4.8.x.
Notez que, tout comme char
sous Windows n’est pas UTF8, sous d’autres systèmes, wchar_t
peut ne pas être UTF16. Donc dans l’ensemble, ce n’est pas susceptible d’être portable. L'ouverture d'un flux avec un nom de fichier wchar_t
n'est pas définie conformément à la norme et il peut être difficile de spécifier le nom de fichier dans char
s car l'encodage utilisé par char varie d'un système d'exploitation à l'autre.
Les versions actuelles de Visual C++ std :: basic_fstream ont une méthode open()
qui prend un wchar_t * selon http://msdn.Microsoft.com/en-us/library/4dx08bh4.aspx .
Utilisez std::wofstream
, std::wifstream
et std::wfstream
. Ils acceptent le nom de fichier unicode. Le nom de fichier doit être wstring
, un tableau de wchar_t
s, ou il doit avoir une macro _T()
ou un préfixe L
avant le texte.
Regardez 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;
}
Depuis C++ 17, il existe un moyen multi-plateforme pour ouvrir un std :: fstream avec un nom de fichier Unicode en utilisant std :: filesystem :: path overload. Jusqu'au C++ 20, vous pouvez créer un chemin à partir d'une chaîne UTF-8 avec std :: filesystem :: u8path . Exemple:
std::ofstream out(std::filesystem::u8path(u8"こんにちは"));
out << "hello";
Après C++ 20, vous pouvez créer un chemin en transmettant UTF-8 au constructeur: std::filesystem::path(u8"こんにちは")
(u8path sera obsolète).
Si vous utilisez Qt mélangé avec std::ifstream
:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));