UTF-8 'durchschleifen'/konvertieren



  • .filmor schrieb:

    Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei.

    Das ist kein encoding nach wchar_t, sondern einfach nach utf32:

    utf8_codecvt_facet is a specialization of std::codecvt specifically designed to handle the case of translating between UTF-8 and UCS-4.



  • Ja, aber UTF-32 ist bis 0xFFFF kompatibel zu UTF-16.



  • und danach willst du unkontrolliert zeichensalat produzieren?



  • Also ersteinmal thx an .filmor für den Versuch.
    Dann Dank an alle anderen, die sich beteiligen, danach eine Antwort:
    Ich sammle INet-Info und gebe sie auf's Display der Logitech G15 aus, auf den im Logitech-SDK mitgelieferten Wrapper.

    Bitte nicht falsch verstehen, ich bin dankbar für jeden Beitrag (auch wenn ihr mich regelmäßig abhängt), aber vielleicht können diejenigen, die '.filmor's Versuch 'zerpflückt' haben, einen eigenen Vorschlag machen.
    Wie würdet ihr denn vorgehen?

    Der Vorteil für mich ist, dass ich mit den Vorschläge mehr anfangen kann, als mit Eurer Diskussion danach 😉

    Zwischenfrage: Habe ich denn überhaupt eine Chance, den UTF-8-Krams gleich zu konvertieren, um danach mit dem normalen std::string zu arbeiten?
    Oder analoges dazu, wenn ich alle meine jetzigen std::string's in std::wstring's ändere?
    Und noch eine Frage:
    Wo genau ist denn jetzt bei mir das Problem, wenn die Sonderzeichen nicht (korrekt) am Display ankommen? Darin, dass ich std::string benutzte, das ich den utf-8 codierten std::string manipuliere (gibt's das so? - mache ich auch nicht immer, geht trotzdem nicht) oder darin, dass die Übergabe ans Display einfach mit c_str() gemacht wird (gleich muss ich mir wohl etwas anhören...)?
    Vielleicht kann man auch da ansetzen.



  • SammyRukka schrieb:

    Bitte nicht falsch verstehen, ich bin dankbar für jeden Beitrag (auch wenn ihr mich regelmäßig abhängt), aber vielleicht können diejenigen, die '.filmor's Versuch 'zerpflückt' haben, einen eigenen Vorschlag machen.
    Wie würdet ihr denn vorgehen?

    Da ich von den Standardfällen ausgehe würde ich tatsächlich die Gefahr eines gewissen Informationsverlustes in Kauf nehmen und intern auf eine 16 bzw. 32 bit-Repräsentation (std::wstring) konvertieren. Da sich aber .filmor scheinbar so gut damit auskennt kann er ja mal sagen wie man mit UTF-8 sinnvoll in einem C++ Programm arbeitet (Vom Einlesen bis hin zur UI-Darstellung). Und das an besten noch mit sinnvollen Quellen im Internet oder in Buchform, nach denen ich schon seit Jahren vergeblich suche (Und es kann nicht sein das man sich eine eigene UTF-8 Bibliothek schreiben muss).

    Vielleicht ist ja das hier (ICU) etwas für dich.

    cu André



  • Schau dir mal an, wie die einzelnen Codierungen (ASCII, UTF-8 UNICODE) aufgebaut sind. Schau nach, was dieses Logitech G15 Display bzw. das Famework dazu kann. Dann kannst du dir ganz leicht überlegen, ob es sinnvoll ist bis zum Ende UTF-8 durchzuschleifen (mit allem was du dabei bedenken musst) oder ob es besser ist gleich beim Einlesen zu konvertieren.



  • @vorschlag:

    SammyRukka schrieb:

    Zwischenfrage: Habe ich denn überhaupt eine Chance, den UTF-8-Krams gleich zu konvertieren, um danach mit dem normalen std::string zu arbeiten?
    Oder analoges dazu, wenn ich alle meine jetzigen std::string's in std::wstring's ändere?

    Bei der Diskussion habe ich den Faden verloren, deshalb ja die Frage. Meinetwegen kann ich gleich konvertieren. Ich hänge nicht so am UTF. Es soll am Ende halt nur normal aussehen, damit meine ich wenigstens die Umlaute.



  • So, sorry, Aber ich habe jetzt 2 Stunden versucht und blicke gar nicht mehr durch:
    - Muss ich dem Compiler (VS5 Express) noch etwas mitgeben, Zeichensatz, Unicodedateien oder so was?
    - Mit welchem Datentyp muss ich denn nun arbeiten? Nach wstring komme ich, den bekomme ich aber nicht in einen LPCTSTR. string benutzen und zur Ausgabe konvertieren, gern, aber wie?
    - ...?
    - 😕 😕

    Jetzt brauche ich eine Woche Urlaub, gut, dass ich sie auch habe 🙂



  • Ojjj, hab ich Euch jetzt verschreckt?

    Jetzt habe ich auch uftcpp getestet.
    Naja, Test ist übertrieben. Ich habe den Kram eingebunden, das Bsp. läuft auch, nur frage ich mich jetzt, wie ich aus dem utf-8- einen normalen std::string machen soll.
    Will sagen: Wie zum T. soll ich das utfcpp anwenden (Sry, bin zu blöd!).



  • Dafür musst du gar nichts machen. std::string benutzt char, was auf allen mir bekannten Plattformen 8-Bit groß ist und damit ohne weiteres UTF-8-Daten halten kann (steht auch irgendwo in der obigen Diskussion ;)).
    Die Verwendung ist jetzt relativ simpel: Wenn du UTF-8-Daten einliest machst du nichts außer der Validitätschecks (die sind in utfcpp implementiert).

    Wenn du dann die Daten in UTF-16 benötigst, dann konvertierst du mit der Bibliothek entsprechend, da das ganze mit Iteratoren arbeitet sollte dafür ein simples std::copy in den Puffer genügen.



  • ist das so schwer zu kapieren wie die Codierungen ausschauen und wie man sie speichert? Hast du dir jemals nen Wikipediaartikel dazu angschaut oder probierst du nur planlos rum?



  • @filmor: Grundsätzlich danke, konkret weiß ich immer noch nicht weiter (s.u.).
    @mal ehrlich: Meinst Du denn eigentlich, ich stelle mich mit Absicht dumm, um Euch zu ärgern?! 😡

    Ich habe doch auch konkrete Fragen gestellt, darauf bekommt man dann aber keine konkreten Antworten. Ich habe Jahre lang Java gemacht und deshalb doch ein wenig das Gefühl für diesen ganzen Zeichenketten-Gump bei C/C++ verloren und durch die 18.000 typedef's dafür steige ich tatsächlich nicht mehr durch. Ich habe mich einfach auch daran gewöhnt, mich mit der Fachlichkeit zu beschäftigen und nicht mit irgendwelchen technischen Unzulänglichkeiten. Das kommt mir ein wenig so wie Linux vor. Das kann ich auch installieren, benutzen und ich komme einigermaßen von A nach B, ab deshalb kann ich noch lange nicht mal eben den Kernel selbst anpassen - was aufgrund der Masse an Doku aber vermutlich einfacher wäre als das hier.

    Was weiß ich denn, ob ich einen UTF-16 benötige? Ich will den Kram doch nur auf dem Display ausgeben und dazu brauche ich einen LPCTSTR, was auch immer genau dahinter steckt.
    Und nein, ich probiere nicht einfach nur rum, ich verstehe das meiste für sich allein auch, habe nur keine Ahnung, wie ich das zusammenführen soll. Und bei der Diskussion vorher scheint das ja auch nicht sooo einfach zu sein.

    Wenn das so einfach wäre, dann hätte man vermutlich auch Xfache Beispiele dafür gefunden.

    Und was ist mit den Fragen zur IDE, wenn's gar nichts damit zu tun hat, dann kann auch das erwähnt werden. Nicht, dass es am Ende an der Konfiguration scheitert.

    Dann helft doch bitte konkret! Ich will hier keinen Code abstauben, aber nach einer Woche erfolglosem Suchen, Lesen und Testen ist das evtl. das einzige, was mir hilft.
    Bei Umlauten kommen halt immer 2 Zeichen bei raus, klar, es wird halt jedes Byte einzeln betrachtet, nur wie ändere ich das und wo an der Stelle hilft mir uftcpp?!

    Da das aber so einfach ist, kann ja evtl. jmd die 3 Zeilen Code hier posten.

    ---- Entschuldigung ----

    Entschuldigt bitte die Ausschweifungen und den vielleicht auch nicht immer passenden Ton. Mir ist hier im Forum schon viel geholfen worden, wenn auch nicht immer wirklich direkt. Trotzdem bin ich nach einer Woche erfolglosem Suchen so weit, dass ich mich etwas über einen solchen Kommentar ärgere, erst recht, wenn nur so ein Kommentar, ohne Ansatz einer Hilfe kommt. Und ja, inzwischen probiere ich vermutlich wirklich nur noch herum - was bleibt mir denn anderes übrig.
    Versuch doch einfach jmd. zu verstehen, der nicht Jahrzehnte lang C programmiert hat und deshalb auch nicht jedes Bit persönlich kennt.



  • Es wäre aber sehr hilfreich, wenn du dich mal zu den Vorschlägen konkret äußern würdest. „Hilft mir nicht weiter“ ist keine sinnvolle Problembeschreibung.

    Dann mal los:
    std::string ist vereinfacht ein Array von char. char ist 8-Bittig, damit ist std::string ein Array von 8-Bit-Elementen. UTF-8 ist (wie man der Wikipedia entnehmen kann) eine Kodierung, die genau solche 8-Bit-Elemente als Speicher braucht.
    Nun bekommst du Daten in diesem Format und validierst sie nach Erhalt zur Sicherheit mit utfcpp (utf8::is_valid).
    Dann machst damit irgendwas tolles und willst es an eine Funktion übergeben, die LPCTSTR übernimmt. Das ist (soweit ich weiß, ich programmiere keinen WinAPI-Kram) abhängig von davon, ob UNICODE gesetzt ist, ein Array von wchar_t, UTF-16-kodiert (die Unterscheidung UCS-2/UTF-16 sei irrelevant) oder ein Array von char, ANSI-kodiert.
    Gehen wir von ersterem Fall aus (kannst du ja forcieren mit

    #ifndef UNICODE
    #error "Ich will aber!!!"
    #endif
    

    . Dann machst du in etwa folgendes:

    // zu übergebende Daten UTF-8-kodiert in daten vom Typ std::string
    TCHAR* buffer = new TCHAR[daten.size() + 1]; // Möglicherweise mehr als notwendig, aber auf jeden Fall genug.
    utf8::utf8to16 (daten.begin (), daten.end (), buffer);
    tolle_funktion_tm (buffer);
    delete[] buffer;
    


  • Kann im Moment nur kurz ins Forum sehen.
    Danke für die Antwort, ich werde das hoffentlich morgen abarbeiten können. 👍

    ---

    Bin da doch nicht ganz davon gekommen...
    Muss ich UNICODE einfach per define setzen oder ist das ein Compilereinstellung? Mit dem 'Unicode-Ausgabedateien verwenden' von Visual Studio Express hat das wohl nichts zu tun, oder?

    Und dann zum Verständnis: Wenn ich UNICODE nicht setzen würde, dann könnte ich den UTF-8-Krams auch nicht verarbeiten, weil LPCTSTR dann wieder nur ein char* wäre und dann wiederum jedes Byte dargestellt werden würde, so wie jetzt.
    wchar_t * aber führt zum Erfolg, weil es 'multibyte'-tauglich ist (Oha, da schwanke ich jetzt).



  • Hallo,

    SammyRukka schrieb:

    Muss ich UNICODE einfach per define setzen oder ist das ein Compilereinstellung?

    Ja, UNICODE wird durch #define bekannt gemacht, kann man im Code direkt machen oder aber in den Projekteinstellungen, die den Präprozessor betreffen.

    SammyRukka schrieb:

    Mit dem 'Unicode-Ausgabedateien verwenden' von Visual Studio Express hat das wohl nichts zu tun, oder?

    Nein.

    SammyRukka schrieb:

    Und dann zum Verständnis: Wenn ich UNICODE nicht setzen würde, dann könnte ich den UTF-8-Krams auch nicht verarbeiten, weil LPCTSTR dann wieder nur ein char* wäre und dann wiederum jedes Byte dargestellt werden würde, so wie jetzt.

    Nein, wenn man UNICODE setzt, legt man fest, dass man mit UTF-16-kodierten Zeichen arbeiten will, weswegen man UTF8 auch mit anderen Datentypen behandeln sollte. Wenn man aber sowieso irgendwann mit UTF-16 arbeiten will und entsprechende Windows-Datentypen/-Funktionen benötigt, dann kann man an die Definition von UNICODE denken.

    SammyRukka schrieb:

    wchar_t * aber führt zum Erfolg, weil es 'multibyte'-tauglich ist (Oha, da schwanke ich jetzt).

    Wenn UNICODE definiert wurde, dann ist z.B. LPCTSTR vom Typ const wchar_t*

    MfG,

    Probe-Nutzer



  • So, hatte endlich wieder etwas Zeit...

    Ich habe das scheinbar jetzt hinbekommen. Vermutlich trickse ich etwas zu viel:

    string l_response = ....;
    int l_laengeXml = utf8::distance(l_response.begin(), l_response.end());
    TCHAR* xmlBuffer = new TCHAR[l_laengeXml];
    utf8::utf8to16 (l_response.begin(), l_response.end(), xmlBuffer);
    l_response = string(xmlBuffer).substr(0, l_laengeXml);
    delete[] xmlBuffer;
    

    Damit kommt der Kram bei mir korrekt an.
    Witzig ist nur, dass das Ganze auch ohne ein #define UNICODE funktioniert 😕.

    btw: UNICODE oder _UNICODE (OK, laut MSN ist _UNICODE richtig)?

    ---

    Aber erst einmal Danke an Euch alle für Eure Zeit und die ertragenen Schmerzen!

    ---

    Nachtrag:
    Ich überlege gerade, ob das 'Zurückkopieren' in den String eigentlich korrekt ist oder nur (wie in meinem Fall) im unteren Bereich des Zeichensatzes funktioniert.
    Ausserdem kommt mir der Teil mit der Länge des Buffers komisch vor, der wurde immer zu lang angelegt, weshalb ich am Ende immer Hieroglyphen hatte und das substr eingeführt habe.
    Das und der Umstand, dass das alles auch ohne #define _UNICODE funktioniert, kann ich mir nicht so recht erklären, ausser, dass _UNICODE evtl. an anderer Stelle definiert wird. Ich habe aber meine Sourcen (inkl. benutztem externen Wrapper) geprüft - auch utf8cpp - ich kann da nichts finden.
    Habt Ihr eine Idee? Ich würde das gern noch etwas mehr verstehen.


Anmelden zum Antworten