Unicode läuft schneller als Ascii ?
-
Artchi schrieb:
Andere Systeme (wie Linux) arbeiten intern mit UTF-8, aber das ist ja deren Entscheidung.
Nur der Vollständigkeit halber: Linux arbeitet intern an den meisten Stellen mit Byte-Folgen und interpretiert dabei nichts. Deswegen kann man z.B. auf einem Linux-Dateisystem ohne weiteres eine Datei mit utf8-kodiertem Dateinamen und im selben Ordner eine andere Datei mit latin1-kodiertem Dateinamen anlegen. Die User-Tools wie die shell werden wahrscheinlich einen der beiden Dateinamen dann nicht richtig anzeigen, aber dem Linux-Kernel selber ist das egal, für den sind das nur uninterpretierte Folgen von Bytes. Das führt gelegentlich zu Problemen mit linux-fremden Dateisystemen wie NTFS, die ein bestimmtes Encoding vorschreiben.
Windows benutzt meines Wissen nach intern schon seit Vista nur noch UTF-16 und nicht mehr UCS-2. UTF-16 ist ein Multiwort-Encoding ist mit Wortbreite von 16 Bit, kann dafür aber wenigstens alle Unicode-Codepoints darstellen.
Nur UCS-2 zu unterstützen ist nicht so praktisch, find ich. Ich hab auch schon LaTeX-Dateien gehabt die Zeichen außerhalb der BMP enthielten (d.h. in UTF-16 nicht mehr mit 16 Bit darstellbar sind), was mit \usepackage[utf8]{inputenc} kein Problem ist.
-
Artchi schrieb:
Das Problem bei UTF-8 ist das die Byte-Länge pro Zeichen dynamisch ist. Also muß doch praktisch bei jedem Buchstaben gerechnet werden, was es nun für ein Wert ist.
Bei fester Byte-Größe (bei NT und wstring ist es immer 2x 1 Byte) muß nichts gerechnet werden.
Das stimmt so auch nicht ganz. Unicode bietet ja auch "Combining characters" an. Das heißt, dass man selbst bei UCS4 schauen muss, ob man jetzt ein Zeichen hat.
-
Christoph schrieb:
Windows benutzt meines Wissen nach intern schon seit Vista nur noch UTF-16 und nicht mehr UCS-2. UTF-16 ist ein Multiwort-Encoding ist mit Wortbreite von 16 Bit, kann dafür aber wenigstens alle Unicode-Codepoints darstellen.
Soweit ich weiß, war das sogar schon ab Windows 2000 so.
-
Um ehrlich zu sein : Ich verstehe jetzt fast nurnoch Bahnhof ;P So viele verschiedenen Kodierungen ;O
Es gibt also verschiedene Kodierungen für Unicode, was zB vom OS abhängt, richtig ?Wenn ich jetzt zB unter Visual C++ 2010 Multibyte Character-Sets einstelle, benutze ich eine bestimmte Kodierung für Unicode, oder ? UTF-8 falls ich das richtig rausgelesen habe.
Und am Ende nochmal meine Frage ;P : Ich kann also generell statt std::string oder char einfach wchar und std::wstring verwenden ? Das scheint ja sogar schneller zu laufen, in allen Arten von Anwendungen.
Mich hatte das nur verwundert, da ich das in noch keinem C++ Lehrbuch oder auch nicht in effective c++ als tipp gesehen habe. Es klingt aber sehr plausibel und wird wohl auch tatsächlich besser sein.
Also std::wstring/wchar > std::string/char, right ?
-
typedef std::basic_string<TCHAR> tstring
(oder halt mit ifdef auf wstring oder tstring mappen)
Und fertig, nun einfach immer brav tstring verwenden und du hast keine Probleme sondern kannst es global mit einer Einstellung wechseln.
(Sobald die Applikation Lokalisiert wird, und auch in asiatische Sprachen, kommst du so oder so nicht um wstring drum herum. Daher machte ich alles immer pauschal wstring und fertig, ob gebraucht oder nicht)
-
David W schrieb:
typedef std::basic_string<TCHAR> tstring
(oder halt mit ifdef auf wstring oder tstring mappen)
Und fertig, nun einfach immer brav tstring verwenden und du hast keine Probleme sondern kannst es global mit einer Einstellung wechseln.
Kann ich mit dem Dateinamen in einem tstring dann auch einen ifstream öffnen? Oder gibt's da einen wifstream?
-
David W schrieb:
typedef std::basic_string<TCHAR> tstring
[...]
Und fertig, nun einfach immer brav tstring verwenden und du hast keine Probleme sondern kannst es global mit einer Einstellung wechseln.Dann liefert aber tstring::length() nur die Länge in Wörtern (TCHAR), nicht die Anzahl der Codepoints. Denn Windows benutzt bei Unicode ja UTF-16, also ein multi-word encoding, wo ein Codepoint 2 wchar_t's lang sein kann. Das hat zum Beispiel insofern Auswirkungen, dass man den String nicht zerschneiden oder kürzen kann ohne (recht aufwändig) das Encoding zu berücksichtigen. Man könnte ja sonst aus Versehen ein Multiwort-Codepoint in der Mitte zerschneiden.
Der Vergleich auf Gleichheit ist genauso problematisch, aber aus anderen Gründen: Unicode definiert, wann zwei Strings äquivalent sein sollen (http://en.wikipedia.org/wiki/Unicode_equivalence). Diese Äquivalenz-Begriffe in Unicode sind *nicht* Byte-für-Byte-Äquivalenz. Zum Beispiel kann ein A mit Kringel dargestellt werden als
- "A" gefolgt von "Kringel über dem letzten Buchstaben"
- "Å"
Falls TCHAR=wchar_t, dann machen die Vergleichsoperatoren von std::basic_string also nicht unbedingt das richtige, wenn man die Strings vorher nicht normalisiert.
-
Dann halt
#ifdef _UNICODE
typedef std::wstring tstring
#else
typedef std::string tstring
#endifIs doch gretzky...
Wenn man mit Strings arbeitet und die Zerpflücken will/muss, muss man sowieso die korrekte Position suchen wo man abschneidet oder einfügt, da ist es egal ob string oder wstring
-
volkard schrieb:
David W schrieb:
typedef std::basic_string<TCHAR> tstring
(oder halt mit ifdef auf wstring oder tstring mappen)
Und fertig, nun einfach immer brav tstring verwenden und du hast keine Probleme sondern kannst es global mit einer Einstellung wechseln.
Kann ich mit dem Dateinamen in einem tstring dann auch einen ifstream öffnen? Oder gibt's da einen wifstream?
Suchst du sowas hier?
typedef std::basic_stringstream<TCHAR> tstringstream;
(Das findet man alles hier im Forum ebenso)
-
David W schrieb:
Dann halt
#ifdef _UNICODE
typedef std::wstring tstring
#else
typedef std::string tstring
#endifIs doch gretzky...
Ja, das ist wirklich egal. Das kommt nämlich genau aufs selbe heraus, denn std::wstring kann auch nicht mit multi-word encodings umgehen. Die combining characters hat man in jedem Fall, auf Gleichheit testen kann man also auch mit std::wstring nicht so, wie das mit Unicode gedacht ist.
David W schrieb:
Wenn man mit Strings arbeitet und die Zerpflücken will/muss, muss man sowieso die korrekte Position suchen wo man abschneidet oder einfügt, da ist es egal ob string oder wstring
Vielleicht möchte ein simples Konsolen-Programm sagen "10 Zeichen des Strings möchte ich ausgeben und falls mehr Zeichen im String sind, wird der Rest durch ... abgekürzt."
Das ist mit Unicode schon eine erstaunlich komplizierte Aufgabe.
-
David W schrieb:
Wenn man mit Strings arbeitet und die Zerpflücken will/muss, muss man sowieso die korrekte Position suchen wo man abschneidet oder einfügt, da ist es egal ob string oder wstring
Die WinAPI bietet diverse Funktionen zum Arbeiten mit Unicode-Strings, welche einem die tricky parts abnehmen. Man sollte die daher auch verwenden, wenn's geht.
-
David W schrieb:
volkard schrieb:
David W schrieb:
typedef std::basic_string<TCHAR> tstring
(oder halt mit ifdef auf wstring oder tstring mappen)
Und fertig, nun einfach immer brav tstring verwenden und du hast keine Probleme sondern kannst es global mit einer Einstellung wechseln.
Kann ich mit dem Dateinamen in einem tstring dann auch einen ifstream öffnen? Oder gibt's da einen wifstream?
Suchst du sowas hier?
typedef std::basic_stringstream<TCHAR> tstringstream;
(Das findet man alles hier im Forum ebenso)Nein, ich suche ifstream. Und der Dateiname soll Unicode sein.
http://www.cplusplus.com/reference/iostream/ifstream/ifstream/
-
volkard schrieb:
David W schrieb:
volkard schrieb:
David W schrieb:
typedef std::basic_string<TCHAR> tstring
(oder halt mit ifdef auf wstring oder tstring mappen)
Und fertig, nun einfach immer brav tstring verwenden und du hast keine Probleme sondern kannst es global mit einer Einstellung wechseln.
Kann ich mit dem Dateinamen in einem tstring dann auch einen ifstream öffnen? Oder gibt's da einen wifstream?
Suchst du sowas hier?
typedef std::basic_stringstream<TCHAR> tstringstream;
(Das findet man alles hier im Forum ebenso)Nein, ich suche ifstream. Und der Dateiname soll Unicode sein.
http://www.cplusplus.com/reference/iostream/ifstream/ifstream/Ich stelle mir jetzt folgendes Szenario vor:
Gegeben ist ein Ordner, der zwei Dateien enthält.
Name der ersten Datei ist ein Zeichen: "A mit Kringel drüber".
Name der zweiten Datei ist zwei Zeichen: "A" + "Kringel über dem letzten Zeichen".Nach Unicode sind diese Namen äquivalent, ein unicode-konformes Dateisystem dürfte also (soweit ich das auffasse) diese Situation überhaupt nicht erst zulassen, weil dann zwei unterschiedliche Dateien mit äquivalentem Dateinamen im selben Ordner liegen.
Mac-Dateisysteme lassen das nicht zu, weil die ihre Dateinamen normalisieren. NTFS speichert seine Dateinamen zumindest in einem einheitlichen Encoding, aber ob Windows die Dateinamen normalisiert, weiß ich nicht. Linux lässt dieses Szenario zu, weil Linux Dateinamen als Bytefolgen ansieht.
Eine Unicode-API zum Dateiöffnen müsste diese beiden Dateinamen aber als äquivalent ansehen. Falls also nur eine dieser beiden Dateien existiert, müsste man sie unter zwei unterschiedlichen Namen öffnen können.
Ich finde zumindest nicht offensichtlich, wie man das korrekt implementiert, ohne dass es zu Problemen führt. Vielleicht ist der Mac-Ansatz gar nicht so schlecht: Dateinamen immer normalisieren. Dann kann es die oben beschriebene Situation nicht geben, weil man die zweite Datei nicht im selben Ordner anlegen kann. Man kann die eine existierende Datei unter beiden Dateinamen öffnen, weil die Namen normalisiert äquivalent sind.
So eine Methode verändert aber eben die Bytes eines Dateinamen und verbietet pauschal Dateinamen, die nicht unicode-kodiert sind. Ich könnte mir Situationen vorstellen, bei denen das zu Bugs führt.