2009-05-04 3 views
42

Sie würden sich nichts so grundlegendes vorstellen wie das Öffnen einer Datei mit der C++ - Standardbibliothek für eine Windows-Anwendung war knifflig ... aber es scheint so zu sein. Mit Unicode hier meine ich UTF-8, aber ich kann in UTF-16 oder was auch immer konvertieren, der Punkt erhält eine ofstream-Instanz von einem Unicode-Dateinamen. Bevor ich meine eigene Lösung hacke, gibt es hier eine bevorzugte Route? Vor allem eine plattformübergreifende?Wie öffne ich einen std :: fstream (ofstream oder ifstream) mit einem Unicode-Dateinamen?

+0

ich dies ist ein [Duplikat] (http://stackoverflow.com/questions/480849/windows-codepage-interactions-with-standard-cc-filenames) Frage. Sehen Sie, ob eine der Antworten dort helfen kann. –

+0

Warum verwenden Sie keine Datentypen wie 'std :: wofstream'? Beachten Sie das ** w **! – sergiol

Antwort

51

Die C++ - Standardbibliothek ist nicht Unicode-aware. char und wchar_t müssen keine Unicode-Kodierungen sein.

Unter Windows wchar_t ist UTF-16, aber es gibt keine direkte Unterstützung für UTF-8 Dateinamen in der Standard-Bibliothek (der char Datentyp auf Windows Unicode ist nicht)

Mit MSVC (und damit die Microsoft STL) , ein Konstruktor für Filestreams vorgesehen ist, die einen const wchar_t* Dateinamen nimmt, so dass Sie den Stream erstellen:

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

jedoch diese Überlastung durch den C++ 11-Standard (es ist nicht nur gewährleistet das Vorhandensein der angegebenen char basierte Version). Es ist auch nicht auf alternativen STL-Implementierungen wie GCCs libstdC++ für MinGW (-w64) ab Version g ++ 4.8.x vorhanden.

Beachten Sie, dass genau wie char unter Windows nicht UTF8 ist, auf anderen OS'es wchar_t möglicherweise nicht UTF16. Insgesamt ist dies wahrscheinlich nicht tragbar. Das Öffnen eines Streams mit dem Dateinamen wchar_t ist nicht gemäß dem Standard definiert, und das Angeben des Dateinamens in char kann schwierig sein, da die von char verwendete Codierung zwischen Betriebssystemen variiert.

+0

Was meinen Sie mit "fstream wird garantiert sowohl wchar_t ..." akzeptieren? Ich habe keinen Zugriff auf den offiziellen 98-Standard, aber ich kann keine Erwähnung eines wchar_t * ctor für basic_fstream in n2857 finden (dh IIUC, der aktuelle C++ 0x-Arbeitsentwurf) –

+0

Hmm, sieht so aus, als ob du recht hast . Ich stehe korrigiert – jalf

+0

@ Éric: vereinbart, die Konstruktoren für basic_fstream sind in 27.8.1.12 des '03-Standards definiert, und es gibt zwei: no-args und char *.fstream ist ein basic_fstream , und für diese Spezialisierung sind keine zusätzlichen Member definiert. –

3

Die aktuellen Versionen von Visual C++ die Std :: Basic_fstream haben eine open() Methode, die eine wchar_t * nach http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx nehmen.

+0

Wird dies letztendlich/theoretisch tragbar sein? –

+3

Nicht alle Betriebssysteme und Dateisysteme unterstützen Unicode-Dateinamen, sodass sie nicht portierbar sind. Aus was ich die wchar_t * open() und Konstruktor auf fstream sammeln kann, sind Microsoft-Erweiterungen, weil NTFS Unicode-Dateinamen unterstützt. –

+3

oder besser, weil NTFS UTF16 verwendet, um Unicode-Dateinamen zu kodieren. Linux unterstützt auch Unicode-Dateinamen, verwendet aber UTF8, so dass die reguläre char * -Version dort funktioniert. – jalf

1

Verwenden Sie std::wofstream, std::wifstream und std::wfstream. Sie akzeptieren Unicode-Dateinamen. Dateiname muss wstring, Array von wchar_t s sein, oder es muss _T() Makro oder Präfix L vor dem Text haben.

+0

Könnten Sie nachweisen, dass 'std :: wfstream'' Unicode' ist? Bis zu meinem bescheidenen Wissen verwenden sie nur 'wchar_t', das ein breites Zeichen ist, normalerweise' 16-Bit'. Aber der Inhalt könnte "Unicode" sein oder nicht. –

+0

Was ich damit meinte ist, dass sie Unicode-Strings akzeptieren, was die Frage beantwortet, nicht wahr? – Brackets

+0

Eigentlich beantworten Sie die Hälfte der Frage: Nehmen wir an, Sie haben Ihren Dateipfad UTF16 in Ihrem wstream (oder UTF8 in Ihrem fstream). Windows akzeptiert keinen Unicode und gibt eine "falsche URL" zurück, wenn Sie Sonderzeichen haben (z. B. Chinesisch). –

0

Werfen Sie einen Blick auf 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; 
} 
Verwandte Themen