[ERLEDIGT] C++ und Boost, Windows 7, UTF-8 äöü Zeichen in Dateien
-
Hallo,
ich habe folgendes Problem:
Angenommen, ich habe zwei Textdateien,
list_utf8.txt (UTF-8 kodiert) und
list_ansi.txt (ANSI kodiert)Beide enthaltet eine einzige Zeile
"C:\Testfile with äöü.dat"Diese leere Datei liegt tatsächlich in C:\Testfile with äöü.dat
Jetzt lese ich mit Boost jeweils die list_utf8.txt und list_ansi.txt, gebe die Zeile aus und prüfe, ob die Datei existiert.
Das ist das Ergebniss:
(Bild)
http://home.arcor.de/gabbafrog/ccc.pngBeide male zeigt er die Umlaute im CMD nicht an (ist nicht so schlimm), aber er findet die Datei nicht, wenn er die UTF-8 Datei liest.
Wie müsste man den folgenden Code ändern, damit das funktioniert?
Danke!
#include <iostream> #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> #include <boost/algorithm/string/predicate.hpp> using namespace std; using namespace boost::filesystem; int main(int argc, char* argv[]) { path p_list_utf ("C:\\list_utf8.txt"); boost::filesystem::ifstream inFileUTF(p_list_utf); while (inFileUTF) { string s; getline(inFileUTF,s); if (inFileUTF) { cout << p_list_utf << endl << s << endl; if ( exists(s) ) { cout << "File exists!" << endl; } else { cout << "File DOES NOT exist!" << endl; } } } path p_list_ansi ("C:\\list_ansi.txt"); boost::filesystem::ifstream inFileANSI(p_list_ansi); while (inFileANSI) { string s; getline(inFileANSI,s); if (inFileANSI) { cout << p_list_ansi << endl << s << endl; if ( exists(s) ) { cout << "File exists!" << endl; } else { cout << "File DOES NOT exist!" << endl; } } } return 0; }
//edit:
Jemand hat hier http://www.cplusplus.com/forum/general/91774/ eine sehr schöne Lösung für das Problem beschrieben.
-
Willkommen in der Coepage-Hölle
Ich bin mir nicht sicher, wie weit boost.filesystem mit UTF8 fertig wird, oder ob es unter Windows mit deren passenden Codierungen gefüttert werden muss. Schau dir auf jeden Fall mal http://utf8everywhere.org/ an, um eine Ahnung zu bekommen, in welches Fallensystem du da getreten bist
-
For Windows-like implementations, including MinGW, path::value_type is wchar_t. The default imbued locale provides a codecvt facet that invokes Windows MultiByteToWideChar or WideCharToMultiByte API with a codepage of CP_THREAD_ACP if Windows AreFileApisANSI()is true, otherwise codepage CP_OEMCP. [Rationale: this is the current behavior of C and C++ programs that perform file operations using narrow character string to identify paths. Changing this in the Filesystem library would be too surprising, particularly where user input is involved. -- end rationale]
du musst boost::filesystem "nur" dazu bringen, die konvertierung von char zu wchar_t über die normale codecvt zu nutzen, sondern ne eigene die das 1 byte format (char) als utf8 spezifiziert, und nicht als iso_xxxx
Ciao ...
-
Hallo,
ich habe oben mein Problem noch einmal konkretisiert, bitte um Hilfe.
@RHBaum
Ich verstehe deine Antwort leider nicht, kannst du das etwas "verständlicher" schreiben? Danke
-
@gubbel
Woher soll derstd::string
wo du die Zeilen reinliest denn wissen dass es einmal ein UTF-8 und einmal ein CP-1252 String ist?
Und wenn es derstd::string
schon nicht mehr weiss, wie soll es dannexists()
wissen?
-
Wie kann ich dem "string" / boost denn sagen, dass es sich um ein UTF-8 Zeichensatz handelt?
-
Dem String kannst du das gar nicht sagen, der hat nämlich gar keinen Platz für diese Information.
Der
Boost.Filesystem
vermutlich auch nicht. Das kannst du aber in derBoost.Filesystem
Doku nachlesen.
-
gubbel schrieb:
//edit:
Jemand hat hier http://www.cplusplus.com/forum/general/91774/ eine sehr schöne Lösung für das Problem beschrieben.in dem verlinkten Beitrag gibt es LINUX und eine Windows Implementierung. die Frage ist nun, ob man das mit boost::locale (ab boost 1.48) auch plattformunabh. hinbekommt
http://www.boost.org/doc/libs/1_52_0/libs/locale/doc/html/charset_handling.htmlzu der verlinkten LINUX Implementierung ist noch zu sagen, daß sie wohl nur funktioniert, wenn auf dem System auch die Locales "en_US.utf8" und "en_US.iso88591" installiert sind. auf einigen Systemen gibt es nur "de_DE.utf8" und sonst nichts weiter
in der C++ Localization library kann man zwar zwischen UTF-8 und UTF-16 konvertieren, aber wohl nicht zwischen UTF-8 und Latin1
http://en.cppreference.com/w/cpp/locale
-
Hihi.
Ich wollte gerade schreiben dass UTF-8 <-> Latin-I eh primitiv ist.
Dann ist mir noch rechtzeitig eingefallen dass bloss UTF-16 <-> Latin-I primitiv ist (bzw. auch UTF-32 <-> Latin-I). Und das auch nur, wenn der UTF-16 String in der passenden Normalform vorliegt.Eieiei, alles doch nicht sooo einfach
-
Mit Qt geht das ganz einfach. QString::fromUtf8, toUft8, fromLatin1, toLatin1...
-
die Umrechnung Latin1<->Unicode ist sehr einfach, selbst Windows-1252<->Unicode ist noch rel. einfach, siehe Weblinks im Wikipedia Artikel
http://de.wikipedia.org/wiki/ISO_8859-1#Weblinksdie Umrechnung Unicode<->UTF-8 ist auch einfach, siehe
http://de.wikipedia.org/wiki/UTF-8#Kodierungähnlich Unicode<->UTF-16
http://de.wikipedia.org/wiki/UTF-16#Kodierungwenn man nur mit Latin1, Windows-1252 und UTF-8/16/32 arbeitet, braucht man so schwere Geschütze wie boost::locale oder ICU library eigentlich nicht