UTF-8 'durchschleifen'/konvertieren



  • OK, also bedeutet das:

    1. Das Speichern zwischendurch ist problemlos.
    2. Das Manipulieren des Strings (trim, append, replace etc.) auch nicht.
    3. Spätestens für die Ausgabe am Ende muss konvertiert werden.

    Wenn das stimmt, dann die Folgefragen:

    4. Kann mir jmd. eine freie und kleine Source nennen, mit der die Konvertierung möglich ist? Ich werde ja kaum der erste sein, der mit C++ aus dem INet XML empfängt. Sollte aber ohne .NET etc. auskommen.
    5. Wenn ich schon konvertieren muss, macht es dann Sinn, die Konvertierung gleich im ersten Schritt vorzunehmen?

    THX @DeSoVoDaMu (und ggf. weitere)



  • utfcpp oder PoCo würden mir da spontan einfallen.



  • 😋 SammyRukka schrieb:

    OK, also bedeutet das:

    1. Das Speichern zwischendurch ist problemlos.
    2. Das Manipulieren des Strings (trim, append, replace etc.) auch nicht.
    3. Spätestens für die Ausgabe am Ende muss konvertiert werden.

    Nein, replace, lenght usw. funktioniert nicht, wenn in deinem std::string utf-8 ist. Nimm was besseres als std::string.



  • utfcpp ist mir auch schon über den Weg gelaufen. Da ich aber nur ein utf8To16 und umgekehrt gefunden habe, habe ich es irgendwie nicht ernst genommen.

    Darf ich nach den letzen beiden Antworten jetzt trotzdem noch mal nachfragen?

    Ich möchte utfcpp einsetzen (finde btw: aber die Lizenz gar nicht):
    1. Kann ich konvertieren und normal meinen std:string benutzen?
    2. Oder brauche ich einen wstring oder was auch immer (wenn ja, was?)?
    3. Mit welchen utfcpp-API-Methoden bekomme ich das denn jetzt hin? Ich blicke noch nicht ganz durch, wie ich den Kram jetzt benutzen soll, gerade, wenn ich den String ggf. manipulieren und das ganze an einen LPCTSTR übergeben will.

    Sorry, gerade für 3., aber ich habe den Bogen wohl noch nicht raus (und hoffentlich nicht trotzdem schon überspannt).

    THX to all! 👍



  • SammyRukka schrieb:

    1. Kann ich konvertieren und normal meinen std:string benutzen?
    2. Oder brauche ich einen wstring oder was auch immer (wenn ja, was?)?

    Du musst dann auch einen Stringtyp verwenden der die konvertierten Daten aufnehmen kann, was wohl auf wstring hinausläuft. Es wird etwas schwierig UTF-8 das ja 1-4 Byte pro Zeichen hat, in einen auf char basierenden Typ verlustfrei zu konvertieren (Zumindest wenn dann jedes Zeichen gleichgroß sein soll).

    cu André



  • asc schrieb:

    Es wird etwas schwierig UTF-8 das ja 1-4 Byte pro Zeichen hat, in einen auf char basierenden Typ verlustfrei zu konvertieren (Zumindest wenn dann jedes Zeichen gleichgroß sein soll).

    Du kannst mir Hoffnung machen. Was heißt das jetzt für mich? Lieber lassen und zum Golf fahren oder viel probieren und immer wieder hier nachfragen?

    btw: Vielleicht sollte ich als XML-Parser einfach TinyXML einsetzen, vielleicht kann der mich korrekt beliefern 😉 😕



  • SammyRukka schrieb:

    asc schrieb:

    Es wird etwas schwierig UTF-8 das ja 1-4 Byte pro Zeichen hat, in einen auf char basierenden Typ verlustfrei zu konvertieren (Zumindest wenn dann jedes Zeichen gleichgroß sein soll).

    Du kannst mir Hoffnung machen. Was heißt das jetzt für mich? Lieber lassen und zum Golf fahren oder viel probieren und immer wieder hier nachfragen?

    Ich habe doch im Vorsatz auch gesagt, das es wohl intern wstring sein sollte.
    Sprich Konvertierung von UTF-8 => std::wstring (Ich glaube unter Windows UTC-2, was auf jedenfall eine fixe Länge hat 1 Buchstabe ist 1 wchar_t). Für den Datenaustausch mag UTF-X ein gutes Format sein, zur internen Verarbeitung ist es sinnvoller mit einem Format zu arbeiten das eine Fixe Buchstabenlänge hat. Vor allem kannst du dann auch sinnvoll die Stringfunktionen darauf anwenden.

    Aber std::string scheidet aus da es auf char als internen Typ basiert. In der Regel reicht auch unter Windows der Typ wchar_t um Verlustfrei Infromationen zu halten (Wobei in der Regel heißt: Es gibt Alphabete auf der Welt die nicht in die ersten 65536 Zeichen passen, was aber für dich schätzungsweise unwichtig ist. Unter vielen Betriebssystemen != Windows ist wchar_t auch 4 Byte groß).

    cu André



  • asc schrieb:

    Ich habe doch im Vorsatz auch gesagt, das es wohl intern wstring sein sollte.
    Sprich Konvertierung von UTF-8 => std::wstring (Ich glaube unter Windows UTC-2, was auf jedenfall eine fixe Länge hat 1 Buchstabe ist 1 wchar_t). Für den Datenaustausch mag UTF-X ein gutes Format sein, zur internen Verarbeitung ist es sinnvoller mit einem Format zu arbeiten das eine Fixe Buchstabenlänge hat. Vor allem kannst du dann auch sinnvoll die Stringfunktionen darauf anwenden.

    Aber std::string scheidet aus da es auf char als internen Typ basiert. In der Regel reicht auch unter Windows der Typ wchar_t um Verlustfrei Infromationen zu halten (Wobei in der Regel heißt: Es gibt Alphabete auf der Welt die nicht in die ersten 65536 Zeichen passen, was aber für dich schätzungsweise unwichtig ist. Unter vielen Betriebssystemen != Windows ist wchar_t auch 4 Byte groß).

    Das stimmt so einfach nicht. wchar_t ist keinen Deut besser als char. Eigentlich sogar schlechter, weil char immerhin halbwegs verlässlich überall die gleiche Größe hat. Auf einem Unicodestring bringt einem die Längenangabe, die einem „primitive“ Bibliotheken liefern können nichts. Die liefern nämlich höchstens die Anzahl der Codepunkte, eine Information die annähernd so nutzlos ist wie die der Anzahl der Bytes eines UTF-8-kodierten Strings.
    Alle anderen Stringfunktionen funktionieren wie gewohnt.

    Ich würde std::string nehmen und durchgängig UTF-8 benutzen. Konvertieren kannst du immernoch, wenn du was ausgeben willst (wenn das überhaupt notwendig werden sollte).



  • .filmor schrieb:

    Das stimmt so einfach nicht. wchar_t ist keinen Deut besser als char.

    Wenn du die Konvertierung die ich erwähne unterschlägst ja. Doch du kannst UTF-8 auch in eine Codierung umwandeln die auf einer festen Zeichenlänge arbeitet. Dann kann man auch die "„primitive“ Bibliotheken" verwenden.

    cu André



  • Und was wäre das? Good-Old-Latin1?



  • .filmor schrieb:

    Und was wäre das? Good-Old-Latin1?

    Nein, wie wäre es aber z.B. mit UTC-2/UTC-4 oder wie sich das schimpft?
    Sprich: Unicodesysteme die sich mit fester Breite im std::wstring unterbringen lassen.

    cu André



  • Hast du meinen Post denn nicht gelesen?

    Es bringt dir absolut nichts, Unicode mit fester „Zeichenlänge“ zu speichern, da ein Unicode-Codepunkt eben nicht zwingend ein Zeichen geschweige denn ein Glyph ist. Der einzige „Vorteil“ ist, dass du dir keine ungültigen Zeichen durch unvorsichtiges abschneiden oder einfügen basteln kannst, aber das kann mit gewissenhafter Programmierung auch gut verhindert werden.
    find etc. funktionieren natürlich auch mit UTF-8-Strings.



  • .filmor schrieb:

    Der einzige „Vorteil“ ist, dass du dir keine ungültigen Zeichen durch unvorsichtiges abschneiden oder einfügen basteln kannst, aber das kann mit gewissenhafter Programmierung auch gut verhindert werden.
    find etc. funktionieren natürlich auch mit UTF-8-Strings.

    Dann zeigt mal wie du ein funktionierendes lenght, find oder replace auf nem utf-8 string in nem std::string machst.



  • Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?



  • .filmor schrieb:

    Hast du meinen Post denn nicht gelesen?

    Es bringt dir absolut nichts, Unicode mit fester „Zeichenlänge“ zu speichern, da ein Unicode-Codepunkt eben nicht zwingend ein Zeichen geschweige denn ein Glyph ist. Der einzige „Vorteil“ ist, dass du dir keine ungültigen Zeichen durch unvorsichtiges abschneiden oder einfügen basteln kannst, aber das kann mit gewissenhafter Programmierung auch gut verhindert werden.
    find etc. funktionieren natürlich auch mit UTF-8-Strings.

    Ich habe jetzt nochmal nachgeschaut. Unter Windows wird intern wohl UCS-2 als 16 Bit Unicode verwendet. Ich Zitiere mal aus der wikipedia, und hebe die Stelle hervor:

    UCS-2 (2-byte Universal Character Set) is an obsolete character encoding which is a predecessor to UTF-16. The UCS-2 encoding form is nearly identical to that of UTF-16, except that it does not support surrogate pairs and therefore can only encode characters in the BMP range U+0000 through U+FFFF. As a consequence it is a fixed-length encoding that always encodes characters into a single 16-bit value. As with UTF-16, there are three related encoding schemes (UCS-2, UCS-2BE, UCS-2LE) that map characters to a specific byte sequence.

    Jetzt sag mir bitte was ich falsch verstehe. Ich weiß selbst das UTF-X nicht zwangsweise 1 Buchstabe für eine Basiseinheit X hat, aber zumindestens unter bestimmten Betriebssystemen wird für die Verwendung in der UI etc. auf ein System mit einer fixen Breite umgewandelt. Und wenn ich weiterhin Windows als beispiel verwende, dient hier dieses System auch als Basis für die Strings unter .Net.

    Mag sein das ich manches falsch verstanden habe, aber sollte ich mich hier irren, so wäre das falschen Informationen über eben diese Formate zuzuschreiben (ich bin beileibe kein Unicodeexperte, habe mich damit aber auch schon länger Beschäftigt und recherchiert).

    Und wenn man in einen System arbeitet wo eine Fixe Länge definiert ist, so sag mir warum die Algorithmen nicht funktionieren sollten.

    cu André



  • @asc es geht wohl eher darum, dass es nichts bringt, auf wchar_t kodierungen umzuschwenken(die normal 16Bit lang sind), um dann wieder daten zu verliereren(eben die surrogate pairs).

    Mein Vorschlag:

    std::basic_string<unsigned int,char_traits<unsigned int> > utf32string.
    

    mit:

    template <typename octet_iterator, typename u32bit_iterator>
    u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
    

    aus der gelinkten utf8 lib. Das reicht zumindest, solange du nicht mit streams rumhantieren musst. ab dann wird es eh, egal welche kodierung, richtig ekelhaft. Wenn man bedenkt, dass es standardlibs ohne wchar_t implementierung gibt, wird einem ganz schwarz vor augen, mit einem für C++ völlig fremden Zeichensatz zu arbeiten.



  • Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.



  • .filmor schrieb:

    Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?

    Das ist ja ein extremer Aufwand, dann musst du jede Benutzereingabe, Konstante usw. zuerst nach UTF-8 Konvertieren. So gut wie keine Funktion gibt dir UTF-8 zurück, wenn du jetzt einmal zu konvertieren vergisst, dann hast du so nen dummen Fehler nach dem du ewig suchst.



  • .filmor schrieb:

    Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.

    Autsch. ok, da braucht man nen eigenen char type. langsam dämemrts mir, warum utf support als standard proposal abgelehnt wurde.



  • sososo schrieb:

    .filmor schrieb:

    Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?

    Das ist ja ein extremer Aufwand, dann musst du jede Benutzereingabe, Konstante usw. zuerst nach UTF-8 Konvertieren. So gut wie keine Funktion gibt dir UTF-8 zurück, wenn du jetzt einmal zu konvertieren vergisst, dann hast du so nen dummen Fehler nach dem du ewig suchst.

    Das ist im wesentlichen auch ein Punkt von mir.

    Ich weiß das Unicode weit mehr als UCS-2 ist (Sorry, ich beschränke mich bei meinen Beispiel jetzt erstmal auf das System das ich kenne: Windows), aber nichts desto trotz wird man es ohnehin schwer haben in Bereichen die vom System nativ nicht abgedeckt werden sinnvoll zu arbeiten. Und innerhalb eines Systemes ist es durchaus ein möglicher 90% Weg, sich auf einen Kompromiss zu beschränken.

    Ich hätte nichts dagegen wenn ich einen (möglichst portablen) Weg finde um mit UTF8 bis UTF-32 wirklich sinnvoll arbeiten zu können (Von dem Dateihandling bis zur UI), nur ist die sinnvolle Beschreibung wie man damit in Programmiersprachen gut umgeht entweder kaum vorhanden, oder es sind einfach zuviel Mülltreffer beim googlen um damit ernsthaft zu arbeiten. Sorry, ich erwarte das man nicht erst den ganzen Unicode-Standard durchackern muss um mit Unicode arbeiten zu können. Mich interessiert auch bei einem Container nicht die konkrete Umsetzung (auch wenn ich vielleicht den ein oder anderen schon selbst implementiert habe).

    Das Problem liegt ja nicht nur bei C++ mit seiner mangelnden Unterstützung, sondern es gibt genügend andere Sprachen die wenn sie Unicode anbieten intern auch mit einem mehr oder weniger weitreichenden Kompromiss arbeiten.

    cu André


Anmelden zum Antworten