UTF-8 lesen?
-
Hallo Forum,
ich möchte die Dateiausgabe (Logfile) eines Programmes lesen. Zuerst dachte ich das es normale ASCII Ausgabe sei, bis ich die Umlaute gesehen habe...
Wie kann ich einen char* der auf einen UTF-8 String zeigt in einen normalen std::wstring schreiben? Ich möchte eigentlich keine extra DLLs (glib, boost, iconv) benutzen. Diese Vorschläge hat die Bordsuche ergeben. Gibt es da nichts einfacheres?
Vielen Dank
-
so weit ich weiß: ja, es gibt keine einfachere methode.
du kannst entweder einer der libs benutzen oder (wovon ich stark abrate) dir selber eine umwandlungstabelle erstellen.
-
*grml* alle schreien nach Arbeit... nur ich hab zuviel davon

-
@ghorst: Danke

-
Wenn deine Umgebung entsprechende Locales zur Verfügung stellt, kannst du auch mit den Standard-Funktionen UTF-8 als wchar_t einlesen. Das ist aber nicht portabel und hängt wirklich von deiner Umgebung ab. So liest der gcc unter Ubuntu Linux völlig ohne Probleme und ganz normal mit wifstream auch UTF-8-Dateien zu wchar_t zu wstring ein, sobald man das Locale "de_DE.utf8" gesetzt hat. Unter Windows wiederum könnte es sehr düster bezüglich mitgebrachter UTF-8-Unterstützung aussehen. Also schau mal deine Entwicklungsumgebung an - vielleicht kannst du dir ja doch einiges an Arbeit sparen

-
Ich arbeite unter Windows und habe mich bereits mit iconv.dll bekannt gemacht.

-
Öhm, es ist eigentlich nicht so viel Arbeit:
template <typename Iterator> static std::size_t get_length (Iterator p) { unsigned char c = static_cast<unsigned char> (*p); if (c < 0x80) return 1; else if (!(c & 0x20)) return 2; else if (!(c & 0x10)) return 3; else if (!(c & 0x08)) return 4; else if (!(c & 0x04)) return 5; else return 6; } template <typename Iterator> static value_type get_value (Iterator p) { const std::size_t len = get_length (p); if (len == 1) return *p; value_type res = static_cast<unsigned char> (*p & (0xff >> (len + 1))) << ((len - 1) * 6); for (--len; len; --len) res |= (static_cast<unsigned char> (*(++p)) - 0x80) << ((len - 1) * 6); return res; }Ich möchte gar nicht behaupten, dass dieser Code völlig korrekt ist (an dem Teil der Bibliothek habe ich verdammt lange nicht mehr gearbeitet ;)), aber er müsste funktionieren und auch halbwegs performant sein.
Wenn du diese Funktion jetzt per transform auf einen UTF-8-String anwendest, erhältst du auf der anderen Seite einen UTF-32-String. Willst du UTF-16 haben, dann schau in der Wikipedia nach, wie man dahin kommt (so hab' ich's hierfür auch gemacht), das sollte auch nicht so schwer sein.
-
eine gute Idee - allerdings sollte sich die Längenbestimmung nicht nur auf den Inhalt des Datenstroms beschränken - wenn der Input nicht validiert wurde (und wer soll das machen, wenn nicht diese Konvertierungsfunktion), dann ist es zumindest möglich, über das Ende hinauszulesen, wenn etwa ein neues Zeichen mit dem letzten Byte beginnt, und dort z.B. 0xff drin steht.
-
Hehe, naja, wie gesagt, das kommt aus einer Bibliothek. Und dort kapsel ich die Iteratoren mit einem "length_checking_iterator". Wenn da irgendein inkrement über das Ende kommt, fliegt ne Exception.
/edit transform geht wahrscheinlich nicht, bzw. dafür müsstest du nochwas an dem Code rumfuschen. Musst du wohl eh, da der aus einer Policy kommt und nicht zum so verwenden gemacht wurde. Aber die Richtung sollte klar sein
