web-dev-qa-db-fra.com

Comment ouvrir un std :: fstream (ofstream ou ifstream) avec un nom de fichier unicode?

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?

45

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 chars car l'encodage utilisé par char varie d'un système d'exploitation à l'autre.

53
jalf

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

3
John Downey

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_ts, ou il doit avoir une macro _T() ou un préfixe L avant le texte.

2
Brackets

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;
}
1
jhasse

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

1
Nikolai

Si vous utilisez Qt mélangé avec std::ifstream:

return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));
1
Andreas Haferburg