75 votes

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

On n'imaginerait pas que quelque chose d'aussi basique que l'ouverture d'un fichier à l'aide de la bibliothèque standard C++ pour une application Windows soit délicat... mais il semble que ce soit le cas. Par Unicode ici, je veux dire UTF-8, mais je peux convertir en UTF-16 ou autre, le but est d'obtenir une instance ofstream à partir d'un nom de fichier Unicode. Avant que je ne bricole ma propre solution, y a-t-il une route préférée ici ? En particulier une solution multiplateforme ?

0 votes

C'est un duplicate question. Voyez si l'une des réponses peut vous aider.

0 votes

Pourquoi n'utilisez-vous pas des types de données comme std::wofstream ? Remarquez le w ¡!

63voto

jalf Points 142628

La bibliothèque standard C++ ne tient pas compte de l'Unicode. char y wchar_t ne sont pas tenus d'être des encodages Unicode.

Sous Windows, wchar_t est UTF-16, mais il n'y a pas de support direct pour les noms de fichiers UTF-8 dans la bibliothèque standard (la fonction char le type de données n'est pas Unicode sous Windows)

Avec MSVC (et donc la STL de Microsoft), un constructeur pour les filestreams est fourni et prend un fichier const wchar_t* nom de fichier, vous permettant 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 la norme C++11 (elle garantit uniquement la présence de l'élément char ). Il n'est pas non plus présent sur les implémentations STL alternatives comme libstdc++ de GCC pour MinGW(-w64), à partir de la version g++ 4.8.x.

Notez que, tout comme char sur Windows n'est pas UTF8, sur d'autres OS'es wchar_t peut ne pas être UTF16. Donc, dans l'ensemble, il est peu probable que cela soit portable. Ouvrir un flux avec un wchar_t n'est pas défini selon la norme, et le fait de spécifier le nom de fichier dans le champ char peut être difficile car l'encodage utilisé par les chars varie selon les systèmes d'exploitation.

4 votes

Une réponse beaucoup plus complète et à jour, incluant la façon de faire ceci avec g++, ainsi que d'autres avenues de l'API Windows, etc. est disponible dans un fil plus récent .

0 votes

@MichalM : non. wchar_t n'est bien sûr qu'un type de caractère de 16 bits de large, qui peut être utilisé pour stocker ce que vous voulez. Il ne se soucie pas des encodages. Mais les API Win32 qui acceptent wchar_t s'attendent à ce qu'ils contiennent des données UTF-16. L'API Windows n'utilise plus l'UCS-2 depuis Windows 2000,

0 votes

@MichalM : Qu'est-ce que est (pas ce dont il est proche, mais ce qui est en fait stocké dans un wchar_t ) est un UTF-16 unité de code . Ce n'est pas l'UCS-2, et bien qu'il soit proche de l'UCS-2, il est encore plus proche d'une unité de code UTF-16 (car c'est ce qu'il est en réalité). est ). L'UTF-16 spécifie qu'un point de code doit être représenté par une ou deux unités de code, ces dernières étant connues sous le nom de paire de substituts.

31voto

Nikolai Points 515

Depuis C++17, il existe un moyen multiplateforme d'ouvrir un std::fstream avec un nom de fichier Unicode en utilisant la fonction std::filesystem::path surcharge. Exemple :

std::ofstream out(std::filesystem::path(u8""));
out << "hello";

3voto

John Downey Points 6729

Dans les versions actuelles de Visual C++, le std::basic_fstream possède une fonction open() qui prend un wchar_t* selon la méthode http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx .

1 votes

Sera-t-il finalement / théoriquement portable ?

3 votes

Les systèmes d'exploitation et les systèmes de fichiers ne prennent pas tous en charge les noms de fichiers Unicode, de sorte que le système ne serait pas portable. D'après ce que j'ai compris, le wchar_t* open() et le constructeur sur fstream sont des extensions Microsoft car NTFS supporte les noms de fichiers Unicode.

3 votes

Ou plutôt, parce que NTFS utilise UTF16 pour coder les noms de fichiers Unicode. Linux supporte également les noms de fichiers unicode, mais utilise UTF8, donc la version char* normale fonctionne dans ce cas.

0voto

Brackets Points 146

Utilisez std::wofstream , std::wifstream y std::wfstream . Ils acceptent les noms de fichiers unicode. Le nom du fichier doit être wstring , tableau de wchar_t ou il doit avoir _T() macro, ou préfixe L avant le texte.

0voto

jhasse Points 538

Jetez un coup d'œil à 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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X