VisialStudio: MultiByte vs Unicode
-
Danke für die ausführliche Antwort!
Das hat dann mal alle meine Fragen beantwortet
Da ich mit VS 2008 entwickle werde ich dann auf Unicode umstellen
-
Wie sieht das denn jetzt aus, wenn ich portierbare Programme für Windows und Linux schreiben will? Verwende ich jetzt auch einfach immer Unicode?
-
daersc schrieb:
Wie sieht das denn jetzt aus, wenn ich portierbare Programme für Windows und Linux schreiben will? Verwende ich jetzt auch einfach immer Unicode?
Wie willst du die WinAPI für Linux benutzen?
-
Ich dachte eher an ein übergreifendes Toolkit wie wxWidgets...
-
xor schrieb:
Die 9x-Windows-Reihe unterstützte nur ANSI (Multibyte) in der WinAPI, dort gab es es kein Unicode (außer man hatte den Unicode-Layer nachinstalliert).
ANSI encoding (korrekt eigentlich Windows 1252) ist doch kein Multibyteencoding. Das passt doch alles schön in ein Byte (256 Zeichen).
-
rüdiger schrieb:
xor schrieb:
Die 9x-Windows-Reihe unterstützte nur ANSI (Multibyte) in der WinAPI, dort gab es es kein Unicode (außer man hatte den Unicode-Layer nachinstalliert).
ANSI encoding (korrekt eigentlich Windows 1252) ist doch kein Multibyteencoding. Das passt doch alles schön in ein Byte (256 Zeichen).
Ja da hast du natürlich recht, wobei meines Wissens "ANSI" (bei API-Funktionen) für so ziemlich alles stehen kann, was aus einzelnen Bytes besteht. Die ANSI-Funktionen arbeiten dann (bitte korregiert mich, wenn ich irre
) unter einem chinesischen Windows mit einem chinesischen Multi-Byte (Double-Byte) String, während sie bei uns mit Windows-1252 (also Single-Byte) nutzen.
Für mich bedeutet daher ANSI unter Windows nur "irgend ein lokal-kodierter Byte-String". Aber das ist so nicht korrekt formuliert ... stimmt
Für das Speichern von Daten hat sich UTF8 für mich bewährt, eben weil man es unter Linux stillschweigend für System-Aufrufe nutzen kann. Unter Windows ist das allerdings eine ungute Herumkonvertiererei. Der einzige Verteil ist, das UTF-8 in ein reguläres char-Array passt und so wunderbar system-unabhängig in Dateien geschrieben werden kann. Wenn man unter Windows Unicode benutzt verwendet man immer UTF-16, da der wchar_t 16 bit breit ist, während wchar_t unter vielen Unices 32 bit breit ist und UTF-32 darstellt.
Wer unter Windows
fwrite(L"Hello World", sizeof(wchar_t), 11, f);
schreibt, bekommt unter Linux mit
wchar_t buffer[20] = { 0 }; fread(buffer, sizeof(wchar_t), 11, f);
Probleme
cu
XOR
-
mir stellt sich auch noch ein Frage
Warum kann man nicht mehr folgendes schreiben:
std::wstring dirINI;
dirINI = SallyAPI::System::SystemHelper::GetModulePath();
dirINI.append("option.ini");Also die letzte Zeile... hiefür muss man ja jetzt
dirINI.append(L"option.ini");
oder
dirINI.append(_T("option.ini"));
schreiben... oder liegt das an Project/Compiler Einstellungen?
-
Was ist genau dier Frage?
Warum der wstring keine automatische Konvertierung von "const char*" hat?Das frage ich mich auch schon immer...
-
Also die technische Erklärung ist einfach: std::string ist ein std::basic_string<char> und std::wstring ist ein std::basic_string<wchar_t>. Und damit kann ein std::string nur mit char umgehen während ein std::wstring nur mit wchar_t umgehen kann
Ich mache daher meist folgendes
#if defined(UNICODE) || defined(_UNICODE) # define tstring wstring #else # define tstring string #endif
Im Projekt benutze ich dann immer den "tstring" und das _T - Makro.
PS: Man kann sich aber auch eine eigene String-Klasse schreiben, wo die Methoden entsprechend überladen sind und dann MultiByteToWideChar / WideCharToMultiByte einsetzen
-
mh, ne eigene Klasse klingt jetzt aber auch nicht gerade reizvoll
Also muss ich überall die Makros verwenden?Was für eins ist da jetzt besser? L oder _T?
-
Der_Knob schrieb:
Was für eins ist da jetzt besser? L oder _T?
L
ist kein Makro, sondern ein Sprachteil von Standard C++.L
sagt dem Kompiler, dass das Stringliteral ein Widestring darstellen soll. Also in Code:char const* c = "hello"; // ist ein char[6] wchar_t const* w = L"hello"; // ist ein wchar_t[6]
_T
ist ein Kompilerabhängiges Makro und nicht Teil von Standard C++. Das Makro_T
ist unter MSVC ca. wie folgt definiert:#if defined(UNICODE) # define _T(x) L ## x #else # define _T(X) x #endif // Wenn UNICODE gesetzt ist, expandiert folgender Ausdruck: _T("hello") // zu L"hello" // Falls UNICODE nicht gesetzt ist, dann wird daraus: "hello"
Wenn du sowieso kein Multibyte verwenden willst und nur Unicode, wozu ich eigentlich auch raten würde, dann verwende immer gleich
L
,wchar_t
undstd::wstring
. Die Makros kannst du dir sparen.Jochen Kalmbach schrieb:
Das frage ich mich auch schon immer...
Ich hoffe, dass dies nicht dein Ernst ist? Ansonsten:
http://www.gotw.ca/gotw/019.htmGrüssli
-
Aber warum nicht auf Multibyte stellen?
Man verwendet normal ASCII Strings und wo man Unicode braucht, nimmt man es halt.
-
Hä? Wie soll denn das gehen? Das ist ja dann ein furchbares durcheinander was kaum durchgängig funktionieren wird...
-
Wenn man auf Unicode stellt, kann man doch gar keine ASCII-Stringliterale mehr definieren?!
In einigen Anwendungen braucht man aber sowohl ASCII/ANSI (whatever lol) und Unicode. Dann stellt man halt auf Multibyte und wo man char* braucht, definiert man char* = "", und wo man wchar_t* braucht, definiert man halt wchar_t* = L""...
Nicht?
-
Hi schrieb:
Wenn man auf Unicode stellt, kann man doch gar keine ASCII-Stringliterale mehr definieren?!
Wie kommst du auf den Unsinn? Grundsätzlich wird nur das Makro
UNICODE
gesetzt. Wodurch die WinAPI Funktionen zur W-Funktion expandieren. Also zum Beispiel ausMessageBox
wird dannMessageBoxW
. Es hindert dich aber niemand daran direktMessageBoxA
aufzurufen.Hi schrieb:
In einigen Anwendungen braucht man aber sowohl ASCII/ANSI (whatever lol) und Unicode. Dann stellt man halt auf Multibyte und wo man char* braucht, definiert man char* = "", und wo man wchar_t* braucht, definiert man halt wchar_t* = L""...
Wenn du auf Unicode stellst, kannst du dies genau gleich verwenden. Daran ändert die Einstellung nichts.
Grüssli
-
xor schrieb:
Für das Speichern von Daten hat sich UTF8 für mich bewährt, eben weil man es unter Linux stillschweigend für System-Aufrufe nutzen kann. Unter Windows ist das allerdings eine ungute Herumkonvertiererei. Der einzige Verteil ist, das UTF-8 in ein reguläres char-Array passt und so wunderbar system-unabhängig in Dateien geschrieben werden kann. Wenn man unter Windows Unicode benutzt verwendet man immer UTF-16, da der wchar_t 16 bit breit ist, während wchar_t unter vielen Unices 32 bit breit ist und UTF-32 darstellt.
UTF-8 und UTF-16 sind ja sogar VariableByte :).
IMHO sind UTF-8 und UTF-32 die einzig sinnvollen Unicodevarianten. Der Rest ist nur für Spezialfälle und Legacysysteme. UTF-8 ist gut, wenn man den Text möglichst klein haben will oder eben für Legacysysteme :). UTF-32 ist gut, wenn man sehr viel zeichenweise machen will.
-
UTF-16 ist gut, wenn man WinAPI Funktionen direkt ansprechen will... das geht nun mal mit UTF-8 nicht da Windows dies nicht als Encoding seiner *A-Funkionen nicht unterstützt.
Fazit: Verwende möglichst immer die *W-Funktionen, wenn Du alle Zeichensätze darstellen willst... und damit verwende auch "wchar_t" bzw. "UTF-16".UTF-32 wird in der Praxis nie eingesetzt...
-
rüdiger schrieb:
UTF-8 ist gut, wenn man den Text möglichst klein haben will oder eben für Legacysysteme :).
Nicht zum Beispiel im asiatischen Raum. Wenn ich mich recht erinnere brauchen gerade chinesische Zeichen in UTF-8 meistens 3 Bytes, während sie in UTF-16 nur 2 Bytes benötigten. Daher wird UTF-16 noch oft im asiatischen Raum eingesetzt.
rüdiger schrieb:
UTF-32 ist gut, wenn man sehr viel zeichenweise machen will.
Kannst du auch bei UTF-32 vergessen. Gewisse Zeichen setzen sich aus mehreren UTF-32 Werten zusammen. Man braucht genauso Indextabellen wie in UTF-8 und UTF-16.
Ein Vorteil von UTF-8 ist, dass man keine Unterscheidung zwischen LE und BE hat.
Grüssli
-
Dravere schrieb:
rüdiger schrieb:
UTF-8 ist gut, wenn man den Text möglichst klein haben will oder eben für Legacysysteme :).
Nicht zum Beispiel im asiatischen Raum. Wenn ich mich recht erinnere brauchen gerade chinesische Zeichen in UTF-8 meistens 3 Bytes, während sie in UTF-16 nur 2 Bytes benötigten. Daher wird UTF-16 noch oft im asiatischen Raum eingesetzt.
Aber nur wenn es sich um reinen Text handelt. Das kommt ja mittlerweile eher selten vor. Wenn Steuerzeichen (sind ja idr aus dem ASCII Satz) enthalten sind, dann ist UTF8 auch hier besser. Wenn du mir nicht glauben willst, dann kannst du es ja einfach ausprobieren. Nimm dir ein paar zh/ja-Wikipedia-Seiten und kodier die einmal als UTF8 und einmal als UTF16. UTF8 gewinnt da deutlich.
Für den japanischen UTF-8: UTF-8 vs. UTF-16: 100453 vs. 171166 Bytes. UTF-8 gewinnt mit 41.3% Vorsprung.
Dravere schrieb:
rüdiger schrieb:
UTF-32 ist gut, wenn man sehr viel zeichenweise machen will.
Kannst du auch bei UTF-32 vergessen. Gewisse Zeichen setzen sich aus mehreren UTF-32 Werten zusammen. Man braucht genauso Indextabellen wie in UTF-8 und UTF-16.
Nein. UTF-32 nutzt 32Bit für alle Zeichen. Es gibt keine Indextabelle. (UCS-4 braucht 24Bit für Zeichen).
-
Jochen Kalmbach schrieb:
UTF-16 ist gut, wenn man WinAPI Funktionen direkt ansprechen will... das geht nun mal mit UTF-8 nicht da Windows dies nicht als Encoding seiner *A-Funkionen nicht unterstützt.
Fazit: Verwende möglichst immer die *W-Funktionen, wenn Du alle Zeichensätze darstellen willst... und damit verwende auch "wchar_t" bzw. "UTF-16".Wie ich sagte: UTF-16 für Legacysysteme.
Jochen Kalmbach schrieb:
UTF-32 wird in der Praxis nie eingesetzt...
Klar, wenn man Unicode mit einfachem Zeichenzugriff haben will. Bei UTF-8/16 muss man ja immer umständlich schauen wo welches Zeichen ist.