Sie würden sich nicht vorstellen, dass etwas so Einfaches wie das Öffnen einer Datei mit der C++-Standardbibliothek für eine Windows-Anwendung schwierig war … aber es scheint so zu sein. Mit Unicode meine ich hier UTF-8, aber ich kann in UTF-16 oder was auch immer konvertieren, der Punkt ist, eine Ofstream-Instanz von einem Unicode-Dateinamen zu bekommen. Bevor ich meine eigene Lösung hacke, gibt es hier eine bevorzugte Route? Vor allem plattformübergreifend?
Wie öffne ich einen std::fstream (ofstream oder ifstream) mit einem Unicode-Dateinamen?
Andreas Beatty
jalf
Die C++-Standardbibliothek ist nicht Unicode-fähig. char
und wchar_t
müssen keine Unicode-Codierungen sein.
Unter Windows, wchar_t
ist UTF-16, aber es gibt keine direkte Unterstützung für UTF-8-Dateinamen in der Standardbibliothek (the char
Datentyp ist unter Windows nicht Unicode)
Mit MSVC (und damit der Microsoft STL) wird ein Konstruktor für Filestreams bereitgestellt, der eine const wchar_t*
Dateiname, sodass Sie den Stream erstellen können als:
wchar_t const name[] = L"filename.txt";
std::fstream file(name);
Diese Überladung wird jedoch nicht vom C++11-Standard spezifiziert (sie garantiert nur das Vorhandensein der char
basierte Version). Es ist auch nicht auf alternativen STL-Implementierungen wie libstdc++ von GCC für MinGW(-w64) ab Version g++ 4.8.x vorhanden.
Beachten Sie, dass genau wie char
unter Windows ist nicht UTF8, unter anderen Betriebssystemen wchar_t
darf nicht UTF16 sein. Insgesamt ist dies also wahrscheinlich nicht tragbar. Öffnen eines Streams gegeben a wchar_t
filename ist nicht nach dem Standard definiert, und die Angabe des Dateinamens in char
s kann schwierig sein, da die von char verwendete Kodierung zwischen den Betriebssystemen variiert.
-
Eine weitaus vollständigere und aktuellere Antwort, einschließlich der Vorgehensweise mit g++ sowie anderer Windows-API-Möglichkeiten usw., ist in einem neueren Thread verfügbar.
– Prost und hth. – Alf
31. Mai 2014 um 14:09 Uhr
-
@MichalM: nein.
wchar_t
ist natürlich nur ein 16-Bit breiter Zeichentyp, in dem alles gespeichert werden kann, was Sie möchten. Es kümmert sich nicht um Codierungen. Aber die Win32-APIs, die akzeptierenwchar_t
Argumente erwarten, dass sie UTF-16-Daten enthalten. Die Windows-API verwendet UCS-2 seit Windows 2000 nicht mehr,– jalf
13. November 2015 um 15:03 Uhr
-
@MichalM: Was ist ist (nicht was es nahe kommt, sondern was ist eigentlich gespeichert in einem
wchar_t
) ist ein UTF-16 Codeeinheit. Es ist nicht UCS-2, und obwohl es UCS-2 nahe kommt, ist es noch näher an einer UTF-16-Codeeinheit (denn das ist es tatsächlich ist). UTF-16 spezifiziert einen Codepunkt, der durch eine oder zwei Codeeinheiten dargestellt werden soll, wobei letztere als Ersatzpaar bezeichnet werden.– jalf
18. November 2015 um 10:43 Uhr
-
Diese Antwort ist seit C++17 veraltet.
– Nicolai
23. Februar 2019 um 12:55 Uhr
-
wirklich? es ist ofc in minigw vorhanden, da minigw msvc copypaste ist
– Алексей Неудачин
2. August 2020 um 8:42 Uhr
Nikolai
Seit C++17 gibt es eine plattformübergreifende Möglichkeit, einen std::fstream mit einem Unicode-Dateinamen mithilfe der std::Dateisystem::Pfad Überlast. Beispiel:
std::ofstream out(std::filesystem::path(u8"こんにちは"));
out << "hello";
-
Als ich dies unter Windows versuchte, hieß die erstellte Datei “ã“ã‚“ã«ã¡ã¯”. (Quelldatei gespeichert als UTF-8). Gibt es andere Schritte, die Sie ausführen müssen, damit dieses Beispiel einen korrekten Dateinamen erstellt?
– Thomm
11. Oktober 2020 um 20:41 Uhr
Die aktuellen Versionen von Visual C++ haben den std::basic_fstream open()
Methode, die ein wchar_t* gemäß nimmt http://msdn.microsoft.com/en-us/library/4dx08bh4.aspx.
-
Wird dies letztendlich / theoretisch portabel sein?
– Andreas Beatty
4. Mai 2009 um 20:52 Uhr
-
Nicht alle Betriebssysteme und Dateisysteme unterstützen Unicode-Dateinamen, sodass sie nicht portierbar wären. Soweit ich weiß, sind wchar_t* open() und der Konstruktor auf fstream Microsoft-Erweiterungen, da NTFS Unicode-Dateinamen unterstützt.
– John Downey
4. Mai 2009 um 22:50 Uhr
-
oder besser gesagt, weil NTFS UTF16 verwendet, um Unicode-Dateinamen zu codieren. Linux unterstützt auch Unicode-Dateinamen, verwendet aber UTF8, sodass dort die reguläre char*-Version funktioniert
– jalf
4. Mai 2009 um 23:12 Uhr
-
Gibt es keine Optionen, wenn der MinGw-Compiler verwendet wird?
– Tebe
5. Januar 2013 um 1:08 Uhr
Klammern
Verwenden std::wofstream
, std::wifstream
und std::wfstream
. Sie akzeptieren Unicode-Dateinamen. Dateiname muss sein wstring
Anordnung von wchar_t
s, oder es muss haben _T()
Makro oder Präfix L
vor dem Text.
Schau mal rein 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;
}
-
noside funktioniert sehr gut … schade, dass es nicht in der Standard-Boost-Distribution enthalten ist; aber es zum Laufen zu bringen ist ziemlich einfach … großartig, endlich ausweichen zu können 🙂
– Benutzer176145
15. Dezember 2019 um 19:50 Uhr
Michael Häphrati
Verwenden
wfstream
anstatt
fstream
und
wofstream
anstatt
ofstream
und so weiter… Sie finden diese Informationen in der iosfwd Header-Datei.
-
noside funktioniert sehr gut … schade, dass es nicht in der Standard-Boost-Distribution enthalten ist; aber es zum Laufen zu bringen ist ziemlich einfach … großartig, endlich ausweichen zu können 🙂
– Benutzer176145
15. Dezember 2019 um 19:50 Uhr
Wenn Sie Qt gemischt mit verwenden std::ifstream
:
return std::wstring(reinterpret_cast<const wchar_t*>(qString.utf16()));
Notiere dass der std::basic_ifstream
Der Konstruktor akzeptiert normalerweise kein a const w_char*
aber auf in der MS-Implementierung von STL tut es. Bei anderen Implementierungen würden Sie wahrscheinlich anrufen qString.utf8()
und verwenden Sie die const char*
ctor.
-
Es gibt kein
ofstream
Konstrukteur das dauert einstd::wstring
Streit. Dies scheint eine Antwort auf eine andere Frage zu sein.– Inspektionsfähig
19. November 2020 um 21:08 Uhr
-
Das ist immer noch ungenau. Das zusätzliche
basic_ifstream
Konstruktoren sind eine Microsoft-spezifische Erweiterung ihrer C++-Bibliotheksimplementierung. Andere Compiler für Windows können diese bereitstellen oder auch nicht. Unabhängig davon, wie diese Antwort erklärt, müssen Sie sich keine Gedanken über Zeichencodierungen oder den überhaupt zu verwendenden Konstruktor machen. Übergeben Sie einfach afilesystem::path
und es funktioniert auf jedem Betriebssystem.– Inspektionsfähig
24. November 2020 um 15:45 Uhr
-
@IInspectable Erneut aktualisiert. Nicht jeder kann C++17 verwenden. Meine Antwort sollte Leuten helfen, die Qt verwenden.
– Andreas Häferburg
27. November 2020 um 10:54 Uhr
-
Wenn Sie C++17 oder die Implementierung der C++-Standardbibliothek von Microsoft nicht verwenden können, gibt es keine sicheren Alternativen. Das Übergeben einer UTF-8-codierten Zeichenfolge für eine bestimmte Plattform ist entweder nicht sicher oder als nicht sicher dokumentiert oder als sicher dokumentiert. Schätzen Sie sich glücklich, wenn Sie zu den letzten beiden Kategorien gehören, obwohl Sie sich realistischerweise in der ersten wiederfinden werden. In diesem Fall die Empfehlung zu verwenden
utf8()
ist fast böswillig, da es häufig nicht fehlschlägt.– Inspektionsfähig
27. November 2020 um 12:27 Uhr
-
@IInspectable Ich weiß nicht, was du von mir willst. Gibt es Ihrer Meinung nach etwas, das getan werden muss? Warum benutzt du ein Wort wie “bösartig”? Das ist keine konstruktive Art, auf ein gemeinsames Ziel hinzuarbeiten.
– Andreas Häferburg
28. November 2020 um 9:49 Uhr
Ich dies ist eine doppelte Frage. Sehen Sie, ob eine der Antworten dort helfen kann.
– Yorgos Pagles
4. Mai 2009 um 20:37 Uhr
Warum verwenden Sie keine Datentypen wie
std::wofstream
? Beachten Sie die w!– sergiol
23. November 2016 um 18:53 Uhr