u16string ausgeben?
-
Hallo Leute,
Ich muss gezwungenermassen mit u16strings arbeiten, die ich ueber die Netzwerkschnittstelle hereinbekomme. Wie kann ich solche Strings korrekt ausgeben? Weder gibt es einen passenden operator << dafuer, noch gibt es ein u16cout.
Gruesse,
Der Kellerautomat
-
DU minst wahrscheinlich UTF-16, oder?
schonmal ICU probiert?
-
Ja, ich habe std::u16strings, die UTF-16 kodiert sind. Sie kommen von einer Java Anwendung.
Eine externe Bibliothek ausser Boost moechte ich ungerne verwenden.
-
Hast du schon versucht, durch den Iteratoren-Paar Konstruktor von
wstring
eine Temporary zu instantiieren und diese auszugeben?std::wcout << std::wstring(str.begin(), str.end());
Soweit ich mir das durchdenke dürfte das doch gehen...
-
Hilft dir http://stackoverflow.com/questions/7232710/convert-between-string-u16string-u32string ?
MfG SideWinder
-
Sone schrieb:
Hast du schon versucht, durch den Iteratoren-Paar Konstruktor von
wstring
eine Temporary zu instantiieren und diese auszugeben?std::wcout << std::wstring(str.begin(), str.end());
Soweit ich mir das durchdenke dürfte das doch gehen...
wstring muss nicht utf-16 kodiert sein. Unter Windows ist es das meines Wissen nach auch nicht. Und unter Linux ist es utf-8.
-
otze schrieb:
Sone schrieb:
Hast du schon versucht, durch den Iteratoren-Paar Konstruktor von
wstring
eine Temporary zu instantiieren und diese auszugeben?std::wcout << std::wstring(str.begin(), str.end());
Soweit ich mir das durchdenke dürfte das doch gehen...
wstring muss nicht utf-16 kodiert sein. Unter Windows ist es das meines Wissen nach auch nicht. Und unter Linux ist es utf-8.
Unter Windows ist unicode (wchar_t = 16Bit) AFAIK eine UCS2 Kodierung und nicht UTF-16, da ein zeichen in ein wchar_t passt. Und mit der UTF-16 Kodierung können für ein zeichen auch 2 oder mehr 16bit blöcke benötigt werden.
Unter linux ist wchar_t 32Bit groß und dann eher brauchbar für eine USC4 Kodierung.
Aber das hat wenig damit zu tun das unter linux die utf-8 kodierung bevorzugt wurde. Diese kodierung hat nur den vorteil, dass bestehende programm auch texte in unicode "verarbeiten" können.PS: Angaben ohne Gewähr dass diese 100%ig richtig sind.
-
Unter Windows kommt nicht UCS-2 sondern UTF-16 zum Einsatz. Dass sich dieser Irrglaube immer noch hält, ist der Wahnsinn.
http://msdn.microsoft.com/en-us/library/windows/desktop/dd374081.aspxFür UTF-16 können zudem nur maximal zwei 16 Bit Blöcke verwendet werden.
http://de.wikipedia.org/wiki/UTF-16@Kellerautomat,
Muss es plattforumunabhängig sein oder kann man z.B. von Windows ausgehen? Eine plattforumabhängige Lösung ist mir nicht bekannt.Grüssli
-
Hallo Kellerautomat,
falls Du bereits C++11 zur Verfügung hat, ist alles mit dem Standard zu machen, wenn Deine Plattform mitspielt (s.u.). Neben einem Konverter
std::wstring_convert
bietet C++11 auch die Facettestd::codecvt_utf16
. Anbei eine kleine Demo, die die Anwendung zeigt:#include <iostream> #include <locale> // wstring_convert #include <codecvt> // codecvt_utf16 #include <algorithm> // transform #include <iterator> // ostream_iterator int main() { using namespace std; cout << "sizeof(wchar_t)=" << sizeof(wchar_t) << endl; string euro = char(0x20) + string(1,char(0xAC)); // Das EURO-Zeichen in UTF-16 string violinenschluessel = "\xD8\x34\xDD\x1E"; string in = violinenschluessel + '\0' + string(1,'1') + '\0' + string(1,'0') + euro; // '$10EUR' in UTF-16 // -- input 'in' in UTF-16 nach s (Unicode) konvertieren std::wstring_convert< std::codecvt_utf16< wchar_t > > converter; wstring s = converter.from_bytes( in ); cout << "Code fuer Violinenschluessel (0x1D11E) = 0x" << hex << int(s[0]) << dec << endl; // -- Ausgabe (mit Berücksichtigung nicht druckbarer Zeichen) const ctype< wchar_t >& ctype_ = use_facet< ctype< wchar_t > >( wcout.getloc() ); transform( begin(s), end(s), ostream_iterator< wchar_t, wchar_t >( wcout << "Ausgabe-> " ), [&ctype_]( wchar_t c )->wchar_t { return c < 0x7fff && ctype_.is( std::ctype_base::print, c )? c: wchar_t('?'); } ); wcout << endl; return 0; }
Bei der Ausgabe ist zu berücksichtigen, dass nicht jedes Device jedes Zeichen darstellen kann. Daher die Ausgabe mit '
transform
' und der Überprüfung mitstd::ctype_base::print
. Wobei ich nicht sicher bin, ob das mitisprint
gemeint ist? Alles was nicht darstellbar ist, wird in der Demo durch '?' ersetzt.Unter VS10 ist das
wchar_t
nur 2Byte groß. Damit kann z.B. der Violinenschlüssel 0x1D11E gar nicht gespeichert werden, das Euro-Zeichen schon. Der Konverter macht aus dem Violinenschlüssel 0xD11E, der Konverter schneidet einfach vorne ab. 0xD11E wird dann später als druckbares Zeichen 'erkannt' - deshalb noch mal die Abfragec < 0x7fff
.Mit VS10 auf der Konsole ergibt sich folgender Output:
sizeof(wchar_t)=2 Code fuer Violinenschluessel (0x1D11E) = 0xd11e Ausgabe-> ?10?
Btw.: die 'schöne' Lösung besteht meines Erachtens in einen
basic_streambuf<wchar_t>
, der gleich die Facettestd::codecvt_utf16
auf den Input(Netzwerkschnittstelle) loslässt und schon ab dem lesenden Stream (gibt es den bei Dir überhaupt?) hat man es dann nur noch mit Unicode-Zeichen zu tun.Gruß
Werner
-
Hallo,
Danke fuer euere bisherigen Loesungen, das scheint ja alles nicht so einfach zu sein. Allerdings hat sich herausgestellt, dass bis auf 1-2 Zeichen nur Zeichen aus dem Extended ASCII Character Set gesendet werden. Daher muss es doch moeglich sein, diese Strings direkt durch abschneiden des jeweils zweiten Bytes in einen normalen std::string umzuwandeln, oder?
Gruesse,
Der Kellerautomat
-
Dravere schrieb:
Unter Windows kommt nicht UCS-2 sondern UTF-16 zum Einsatz. Dass sich dieser Irrglaube immer noch hält, ist der Wahnsinn.
http://msdn.microsoft.com/en-us/library/windows/desktop/dd374081.aspxOk sie verwenden "mittlerweile" UTF-16. Aber erst ab Windows 2000 wird UTF-16 voll unterstützt. Vorher war es UCS-2.