UCS-2, UTF-8, UTF-16, UTF-32, WTF?



  • @DocShoe sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    Von der Idee, Zeichen als einzelne Byte zu behandeln muss man sich dann wohl trennen, wenn man Unicode verwendet.

    Jein, man kann natürlich intern mit wchar_t arbeiten und muss so nicht den Programmcode abändern, aber man konvertiert dann ständig zwischen Programm interner Kodierung (UCS-4) und API Kodierung (UTF-8 bzw. UTF-16). Ob das so sinnvoll ist?

    Da es letztlich im Forum die Frage nach ncurses gab (hat natürlich nichts mit Windows zu tun), habe ich mir die ncursesw Library angeschaut. Da wird immer wchar_t an die Library übergeben und in cchar_t konvertiert (wchar_t plus Attribute fürs Terminal: Farbe, Stil …). D.h. es gibt auch APIs, die mit wchar_t arbeiten. Weshalb Windows ausgerechnet UTF-16 verwendet ist mir persönlich schleierhaft, weil es weder die Vorzüge einer gleichen API bietet wie UTF-8 aber nicht problemlos mit allen Unicodezeichen funktioniert wie UCS-4. Windows erschien mir noch nie logisch durchdacht zu sein.



  • @Quiche-Lorraine:
    Unsere Dateien tragen alle eine Versionsnummer, dann muss man strings beim Einlesen abhängig von der Versionsnummer behandeln.

    @john-0
    Ne, wchar_t hilft da nicht weiter, weil man bei UTF-16 ähnliche Probleme wie bei UTF-8 hat, nämlich dass ein sich Zeichen aus bis zu zwei wchar_t zusammensetzen darf. Bis Windows2000 hat Microsoft UCS-2 benutzt, dabei wurde jedes Zeichen mit genau 2 Byte kodiert.



  • @DocShoe sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    Unsere Dateien tragen alle eine Versionsnummer, dann muss man strings beim Einlesen abhängig von der Versionsnummer behandeln.

    Wird dann spannend die Versionsnummer zu lesen wenn man noch nicht weiss welches Encoding das File verwendet. Ich würde aber empfehlen für Files auf jeden Fall UTF-8 zu verwenden - selbst wenn ihr euch entschiesst im Speicher UTF-16 zu verwenden. Dann ist das mit Versionsnummer lesen vermutlich auch kein grosses Problem, weil UTF-8 ja ASCII kompatibel ist. (Gut, zu prüfen ob ein Textfile welches z.B. garantiert irgendwo auch ASCII Zeichen enthält UTF-16 ist, ist jetzt auch nicht so schwer. Aber wer will schon UTF-16 Textfiles verwenden?)

    Von der Idee, Zeichen als einzelne Byte zu behandeln muss man sich dann wohl trennen, wenn man Unicode verwendet.

    Das kommt drauf an was man mit den Zeichen machen will, und um welche Zeichen es sich handelt. Ein str[0] == '#' oder so funktioniert auch ohne Probleme mit UTF-8 oder UTF-16. Genau so ein str.back() == '?'. Mit UTF-8 geht sogar noch strchr (und mit UTF-16 wcschr`) so lange man nur die Position im Speicher braucht und nicht wissen muss um den wievielten Codepoint im String es sich handelt.

    Wenn man dagegen etwas ala str[0] == userDefinedCharacter hat, dann ja, dann wird das eine Spur komplizierter. Dann muss da ein begins_with(str, userDefinedCharacter) statt dessen hin.



  • @hustbaer
    Das sind keine Textdateien, sondern Binärdateien, die unter anderem auch Text enthalten. Du bist vermutlich noch bei deiner Textverarbeitung. Der Dateiheader hat eine ASCII Signatur und unter anderem 4 uint für Major, Minor, Release und Build Version. Den Header kann ich also immer richtig lesen und anhand der Versionsnummer weiter entscheiden, wie Text behandelt wird (ANSI/UTF-8). Seh da kein Problem.



  • @DocShoe sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    Das sind keine Textdateien, sondern Binärdateien, die unter anderem auch Text enthalten. Du bist vermutlich noch bei deiner Textverarbeitung

    Naja bis jetzt wurde von dir auch nie gesagt dass es sich um binär daten handelt, welche auch texte enthalten können.



  • @DocShoe sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    Das sind keine Textdateien, sondern Binärdateien, die unter anderem auch Text enthalten.

    OK 👍

    Du bist vermutlich noch bei deiner Textverarbeitung.

    Nönö. Dass du keine Textverarbeitung machst hatte ich schon verstanden. Nur dass heute die meisten Configfiles und auch sehr viele Datenfile Formate textbasiert sind. Und natürlich das was @firefly angedeutet hat: du hattest ja geschrieben dass da Texte drin stehen, und da hab ich dann automatisch Textfile gedacht. Heisst nicht dass du was falsch gemacht hast, nur zur Erklärung wieso ich Textfile angenommen hatte.

    Der Dateiheader hat eine ASCII Signatur und unter anderem 4 uint für Major, Minor, Release und Build Version. Den Header kann ich also immer richtig lesen und anhand der Versionsnummer weiter entscheiden, wie Text behandelt wird (ANSI/UTF-8). Seh da kein Problem.

    Ich auch nicht 🙂



  • @DocShoe sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    @john-0
    Ne, wchar_t hilft da nicht weiter, weil man bei UTF-16 ähnliche Probleme wie bei UTF-8 hat, nämlich dass ein sich Zeichen aus bis zu zwei wchar_t zusammensetzen darf. Bis Windows2000 hat Microsoft UCS-2 benutzt, dabei wurde jedes Zeichen mit genau 2 Byte kodiert.

    Ich sehe gerade, dass UNIX/Linux und Windows wchar_t verschieden definieren 😞 . Nun denn, die Welt könnte so einfach sein, warum machen wir sie nicht komplizierter. Also, UNIX/Linux definiert wchar_t als UTF-32 (UCS-4 wurde als Name wohl beerdigt) sizeof(wchar_t)==4 und somit hat man damit immer feste Längen bei std::wstring. Ursprünglich hieß das ganze UCS-4 wurde dann aber mit UTF-16 kompatiblen gemacht und somit entstand dann UTF-32.



  • @john-0 sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    somit hat man damit immer feste Längen bei std::wstring

    Mit der aussage wäre ich vorsichtig 🙂 Aktuell mag 32Bit für alle aktuellen Unicode Zeichen reichen.
    Da aber immer mehr Zeichen dem Unicode Standard hinzugefügt werden, wird irgendwann 32Bit nicht mehr reichen um alle Zeichen kodieren zu können.



  • @firefly sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    Mit der aussage wäre ich vorsichtig 🙂 Aktuell mag 32Bit für alle aktuellen Unicode Zeichen reichen.

    Es sind ja keine 32Bit sondern deutlich weniger, aktuell wird nur bis 0x0010FFFF kodiert. Die ursprüngliche Version erlaubte noch Codes bis 0x7FFFFFFF. Das kann man gut in der RFC-2279 und RFC-3629 nachlesen.



  • @firefly sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    @john-0 sagte in UCS-2, UTF-8, UTF-16, UTF-32, WTF?:

    somit hat man damit immer feste Längen bei std::wstring

    Mit der aussage wäre ich vorsichtig 🙂 Aktuell mag 32Bit für alle aktuellen Unicode Zeichen reichen.
    Da aber immer mehr Zeichen dem Unicode Standard hinzugefügt werden, wird irgendwann 32Bit nicht mehr reichen um alle Zeichen kodieren zu können.

    Der Unicode Codespace ist als 0 ... 0x10FFFF definiert. UTF-16 kann auch gar nicht mehr darstellen. UTF-8 streng genommen auch nicht, da Bytesequenzen die Codepoints > 0x10FFFF ergeben würden als ungültig definiert sind.

    Trotz dem wir schon tonnenweise Müll (z.B. Emojis) reindefiniert haben und ein paar richtig dicke Dinger wie Han oder Hangul dabei sind, sind nichtmal 30% des Codespace verwendet.

    Den Codespace zu erweitern wäre auch ein "breaking change". Man könnte auch sagen dass sich daran nie etwas ändern kann, weil das was man dann hätte nicht mehr Unicode wäre. Weiters könnten wir dann viele der existierenden Programme mit Unicode Support in the Tonne treten.

    Also ich würde mir da keine grossen Sorgen machen.


Log in to reply