Unicode



  • Hi,

    ich bastle an einem kleinen Spiel, dass Daten u.A. von verschiedenen Schnittstellen (zB SQLite, TinyXML2) bekommt.
    Diese Daten können auch Umlaute etc. enthalten.

    Was ist die beste Möglichkeit damit umzugehn?
    Bisher hab ich versucht, mit std::string (also UTF8) zu arbeiten. Leider komme ich nicht damit klar. Für meine Font-Engine benötige ich zB die Anzahl an Zeichen eines Strings, sowie die Charcode der einzelnen Zeichen als Decimal.
    Bisher konnte ich trotz jeder Menge googlen noch keine Lösung dafür finden.

    Die zweite Möglichkeit wäre, ich benutze std::wstring und konvertiere alle Input-Strings nach UTF16/32.

    Im Internet finde ich nur wiedersprüchliche Informationen. Die Einen sagen, unbedingt UTF8 (std::string) benutzen, die Anderen sagen, std::wstring benutzen.

    Was wäre die beste Lösung für den Umgang mit Unicode?

    Edit: Plattform sollte sowohl Windwos, als auch Linux und Mac sein.

    Gruß



  • Raven280438 schrieb:

    Was wäre die beste Lösung für den Umgang mit Unicode?

    Es gibt keine. Alle Lösungen haben Vor- und Nachteile.
    Ich würde versuchen, möglichst selten zu konvertieren.



  • QString



  • Beides ist fuer Unicode nicht geeignet. Der C++ Standard kennt naemlich keinen UTF-8 Standard.
    Ich wuerde dafuer eine Biliothek verwenden, ICU ist beispielsweise ziemlich populaer: http://site.icu-project.org/
    Wenn du Qt verwendest, ist natuerlich auch QString eine Moeglichkeit.

    Zur Frage UTF-8 oder UTF-16: http://www.utf8everywhere.org/


  • Mod

    Der C++ Standard kennt naemlich keinen UTF-8 Standard.

    N3337 1.7/1 schrieb:

    A byte is at least large enough to contain any member of the basic execution character set (2.3) and the eight-bit code units of the Unicode UTF-8 encoding form [...]

    Seit C++11 gibt es dafuer mehr Unterstuetzung; siehe bspw. Facets wie codecvt_utf8 , oder Strings ( bspw. std::u16string ).

    Das Beispiel von der Referenz zeigt auch gleich Konvertierungen:

    // UTF-8 data. The character U+1d10b, musical sign segno, does not fit in UCS2
        std::string utf8 = u8"z\u6c34\U0001d10b";
    
        // the UTF-8 / UTF-16 standard conversion facet
        std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf16conv;
        std::u16string utf16 = utf16conv.from_bytes(utf8);
        std::cout << "UTF16 conversion produced " << utf16.size() << " code points:\n";
        for (char16_t c : utf16)
            std::cout << std::hex << std::showbase << c << '\n';
    


  • Schau mal, wer alles NICHT UTF-8 benutzt:

    Java-Runtime (UTF-16), Mac OS X (UTF-32), Windows NT (UTF-16) und die .NET Runtime auch nicht.

    So grob mal gefragt: ist das negativ aufgefallen, das die gängigen Systeme UTF-16 oder UTF-32 nutzen? Nö.

    Was ist der Vorteil? Performance! Feste Bit-Breiten sind einfach schneller zu verarbeiten. Pro 16 bzw. 32 Bit ein Zeichen.

    Bei UTF-8 hast du variable Breiten, und dann muss bei jedem Zeichen der Code überprüft werden. Außerdem hat UTF-8 je nach Zeichencode mehr Speicherverbrauch als die anderen UTFs.

    UTF-8 hat meines Wissens nur einen Vorteil: wenn es sich nur um ASCII-Zeichen handelt, hat man weniger Speicherverbauch als UTF-16/32. Aber sobald z.B. Umlaute, oder gar arabisch oder chinesisch dazu kommt, ist der Vorteil dahin.



  • Artchi schrieb:

    Schau mal, wer alles NICHT UTF-8 benutzt:

    Java-Runtime (UTF-16), Mac OS X (UTF-32), Windows NT (UTF-16) und die .NET Runtime auch nicht.

    DAS Argument.

    So grob mal gefragt: ist das negativ aufgefallen, das die gängigen Systeme UTF-16 oder UTF-32 nutzen? Nö.

    Ja.

    Was ist der Vorteil? Performance! Feste Bit-Breiten sind einfach schneller zu verarbeiten. Pro 16 bzw. 32 Bit ein Zeichen.

    UTF-16 hat auch nicht feste Bitbreiten.

    Bei UTF-8 hast du variable Breiten, und dann muss bei jedem Zeichen der Code überprüft werden. Außerdem hat UTF-8 je nach Zeichencode mehr Speicherverbrauch als die anderen UTFs.

    Ähm, nein?



  • Artchi schrieb:

    Was ist der Vorteil?

    Gute Frage, darauf habe ich keine gute Antwort.

    Performance!

    lol

    Feste Bit-Breiten sind einfach schneller zu verarbeiten. Pro 16 bzw. 32 Bit ein Zeichen.

    Was verstehst du unter Zeichen? Einen Codepoint?

    Bei UTF-8 hast du variable Breiten, und dann muss bei jedem Zeichen der Code überprüft werden.

    lol

    Außerdem hat UTF-8 je nach Zeichencode mehr Speicherverbrauch als die anderen UTFs.

    Öhm...

    UTF-8 hat meines Wissens nur einen Vorteil: wenn es sich nur um ASCII-Zeichen handelt, hat man weniger Speicherverbauch als UTF-16/32. Aber sobald z.B. Umlaute, oder gar arabisch oder chinesisch dazu kommt, ist der Vorteil dahin.

    lol



  • keinjavafanboy schrieb:

    Feste Bit-Breiten sind einfach schneller zu verarbeiten. Pro 16 bzw. 32 Bit ein Zeichen.

    Was verstehst du unter Zeichen? Einen Codepoint?

    Das ist der springende Punkt. Die Anzahl von Unicode-Entitäten sagt nicht viel darüber aus, was dargestellt wird. Zum Einen ist nicht eine 32-Bit entität mit einem Zeichen gleichzusetzen(Chinesisch und Arabisch) es gibt auch Steuerzeichen (Textrichtung).

    Es macht in der Praxis keinen Unterschied, welches Encoding man verwendet. Sobald man davon ausgeht, dass im String was komplexeres ist als lateinische Buchstaben, dann hat die Textlänge keine Bedeutung mehr.



  • otze schrieb:

    Sobald man davon ausgeht, dass im String was komplexeres ist als lateinische Buchstaben, dann hat die Textlänge keine Bedeutung mehr.

    Mist. Eigentlich müßte ich Dich verfluchen dafür, daß Du das gesagt hast.
    Andererseits auch nicht, es macht mir das Leben doch viel leichter.



  • otze schrieb:

    Es macht in der Praxis keinen Unterschied, welches Encoding man verwendet. Sobald man davon ausgeht, dass im String was komplexeres ist als lateinische Buchstaben, dann hat die Textlänge keine Bedeutung mehr.

    Keine Bedeutung für was?



  • Hi,

    wie gesagt:

    Im Internet finde ich nur wiedersprüchliche Informationen. Die Einen sagen, unbedingt UTF8 (std::string) benutzen, die Anderen sagen, std::wstring benutzen.

    😉





  • Satzproblem schrieb:

    Keine Bedeutung für was?

    Die Anzahl Code-Units(8Bit/UTF-8, 16Bit/UTF-16, 32Bit/UTF-32) muß nicht gleich der Anzahl Buchstaben sein.

    äaä

    Vier Code-Units aber nur drei Buchstaben.
    Mein Firefox stellt's übrigens falsch dar, Chrome macht's richtig. Auch daran kann man sehen, daß die Sache nicht ganz trivial ist.
    Die beiden Varianten des 'ä' sollen übrigens gleich behandelt werden z.B. in der Sortierung. Wer soll das mit beliebigen Zeichen beherrschen?
    Ich denke, daß Unicode an einigen Stellen einfach kaputt ist.



  • Artchi schrieb:

    Schau mal, wer alles NICHT UTF-8 benutzt:

    Java-Runtime (UTF-16), Mac OS X (UTF-32), Windows NT (UTF-16) und die .NET Runtime auch nicht.

    Nach meiner Kenntnis nutzen Windows, Java und .Net nicht UTF-16 sondern UCS-2 (Entspricht im wesentlichen UTF-16, aber begrenzt auf Unicode 3.0 und damit fixen Bytelängen von 2 Byte).



  • Nein, sie benutzen UTF-16. (Ich glaube, Windows hat bis inklusive NT UCS-2 verwendet)



  • Hi,

    ich tendiere dazu, UTF8 zu benutzen (da die Schnittstellen das beherrschen).

    Allerdings hab ich trotz Googeln immernoch keine Lösung für mein Problem gefunden:

    Für meine Font-Engine benötige ich zB die Anzahl an Zeichen eines Strings, sowie die Charcode der einzelnen Zeichen als Decimal.

    Gruß



  • benutze doch ein vorgefertigte engine die utf kann. Das wonach du fragst ist nicht trivial, wie man an dem Beispiel von Caligulaminus sieht.



  • Satzproblem schrieb:

    otze schrieb:

    Es macht in der Praxis keinen Unterschied, welches Encoding man verwendet. Sobald man davon ausgeht, dass im String was komplexeres ist als lateinische Buchstaben, dann hat die Textlänge keine Bedeutung mehr.

    Keine Bedeutung für was?

    Caligulaminus schrieb:

    Satzproblem schrieb:

    Keine Bedeutung für was?

    Die Anzahl Code-Units(8Bit/UTF-8, 16Bit/UTF-16, 32Bit/UTF-32) muß nicht gleich der Anzahl Buchstaben sein.

    Das sagt doch nicht der Satz aus. Wie sollte der Satz dann lauten?

    "Sobald man davon ausgeht, dass im String was komplexeres ist als lateinische Buchstaben, dann hat die Textlänge keine Bedeutung für die Anzahl Code-Units mehr." ? 😕 Das würde ja nicht stimmen, die Anzahl Code-Units ändert sich so gut wie immer, wenn sich die Textlänge ändert.



  • Raven280438 schrieb:

    Für meine Font-Engine benötige ich zB die Anzahl an Zeichen eines Strings, sowie die Charcode der einzelnen Zeichen als Decimal.

    for(char c : utf8string)
    {
        if(!(c & 0x80) || (c & 0xC0) == 0xC0)
            ++counter;
    }
    

    Ungetestet.

    Zählt die code points (siehe meinen vorletzten Post).
    Dafür gibt's bestimmt was fertiges, ich weiß aber grad' nix.

    Was die Codes angeht mußt Du entweder von Hand dekodieren oder eine von den UTF-8 zu UTF-32 Konvertierungsfunktionen (->google) benutzen. In UTF-32 steht dann in jedem 32-Bit-Wort ein Unicode code point.

    ~Edit: Code korrigiert, unit->point~


Anmelden zum Antworten