UTF-8 'durchschleifen'/konvertieren
-
asc schrieb:
Es wird etwas schwierig UTF-8 das ja 1-4 Byte pro Zeichen hat, in einen auf char basierenden Typ verlustfrei zu konvertieren (Zumindest wenn dann jedes Zeichen gleichgroß sein soll).
Du kannst mir Hoffnung machen. Was heißt das jetzt für mich? Lieber lassen und zum Golf fahren oder viel probieren und immer wieder hier nachfragen?
btw: Vielleicht sollte ich als XML-Parser einfach TinyXML einsetzen, vielleicht kann der mich korrekt beliefern
-
SammyRukka schrieb:
asc schrieb:
Es wird etwas schwierig UTF-8 das ja 1-4 Byte pro Zeichen hat, in einen auf char basierenden Typ verlustfrei zu konvertieren (Zumindest wenn dann jedes Zeichen gleichgroß sein soll).
Du kannst mir Hoffnung machen. Was heißt das jetzt für mich? Lieber lassen und zum Golf fahren oder viel probieren und immer wieder hier nachfragen?
Ich habe doch im Vorsatz auch gesagt, das es wohl intern wstring sein sollte.
Sprich Konvertierung von UTF-8 => std::wstring (Ich glaube unter Windows UTC-2, was auf jedenfall eine fixe Länge hat 1 Buchstabe ist 1 wchar_t). Für den Datenaustausch mag UTF-X ein gutes Format sein, zur internen Verarbeitung ist es sinnvoller mit einem Format zu arbeiten das eine Fixe Buchstabenlänge hat. Vor allem kannst du dann auch sinnvoll die Stringfunktionen darauf anwenden.Aber std::string scheidet aus da es auf char als internen Typ basiert. In der Regel reicht auch unter Windows der Typ wchar_t um Verlustfrei Infromationen zu halten (Wobei in der Regel heißt: Es gibt Alphabete auf der Welt die nicht in die ersten 65536 Zeichen passen, was aber für dich schätzungsweise unwichtig ist. Unter vielen Betriebssystemen != Windows ist wchar_t auch 4 Byte groß).
cu André
-
asc schrieb:
Ich habe doch im Vorsatz auch gesagt, das es wohl intern wstring sein sollte.
Sprich Konvertierung von UTF-8 => std::wstring (Ich glaube unter Windows UTC-2, was auf jedenfall eine fixe Länge hat 1 Buchstabe ist 1 wchar_t). Für den Datenaustausch mag UTF-X ein gutes Format sein, zur internen Verarbeitung ist es sinnvoller mit einem Format zu arbeiten das eine Fixe Buchstabenlänge hat. Vor allem kannst du dann auch sinnvoll die Stringfunktionen darauf anwenden.Aber std::string scheidet aus da es auf char als internen Typ basiert. In der Regel reicht auch unter Windows der Typ wchar_t um Verlustfrei Infromationen zu halten (Wobei in der Regel heißt: Es gibt Alphabete auf der Welt die nicht in die ersten 65536 Zeichen passen, was aber für dich schätzungsweise unwichtig ist. Unter vielen Betriebssystemen != Windows ist wchar_t auch 4 Byte groß).
Das stimmt so einfach nicht. wchar_t ist keinen Deut besser als char. Eigentlich sogar schlechter, weil char immerhin halbwegs verlässlich überall die gleiche Größe hat. Auf einem Unicodestring bringt einem die Längenangabe, die einem „primitive“ Bibliotheken liefern können nichts. Die liefern nämlich höchstens die Anzahl der Codepunkte, eine Information die annähernd so nutzlos ist wie die der Anzahl der Bytes eines UTF-8-kodierten Strings.
Alle anderen Stringfunktionen funktionieren wie gewohnt.Ich würde std::string nehmen und durchgängig UTF-8 benutzen. Konvertieren kannst du immernoch, wenn du was ausgeben willst (wenn das überhaupt notwendig werden sollte).
-
.filmor schrieb:
Das stimmt so einfach nicht. wchar_t ist keinen Deut besser als char.
Wenn du die Konvertierung die ich erwähne unterschlägst ja. Doch du kannst UTF-8 auch in eine Codierung umwandeln die auf einer festen Zeichenlänge arbeitet. Dann kann man auch die "„primitive“ Bibliotheken" verwenden.
cu André
-
Und was wäre das? Good-Old-Latin1?
-
.filmor schrieb:
Und was wäre das? Good-Old-Latin1?
Nein, wie wäre es aber z.B. mit UTC-2/UTC-4 oder wie sich das schimpft?
Sprich: Unicodesysteme die sich mit fester Breite im std::wstring unterbringen lassen.cu André
-
Hast du meinen Post denn nicht gelesen?
Es bringt dir absolut nichts, Unicode mit fester „Zeichenlänge“ zu speichern, da ein Unicode-Codepunkt eben nicht zwingend ein Zeichen geschweige denn ein Glyph ist. Der einzige „Vorteil“ ist, dass du dir keine ungültigen Zeichen durch unvorsichtiges abschneiden oder einfügen basteln kannst, aber das kann mit gewissenhafter Programmierung auch gut verhindert werden.
find etc. funktionieren natürlich auch mit UTF-8-Strings.
-
.filmor schrieb:
Der einzige „Vorteil“ ist, dass du dir keine ungültigen Zeichen durch unvorsichtiges abschneiden oder einfügen basteln kannst, aber das kann mit gewissenhafter Programmierung auch gut verhindert werden.
find etc. funktionieren natürlich auch mit UTF-8-Strings.Dann zeigt mal wie du ein funktionierendes lenght, find oder replace auf nem utf-8 string in nem std::string machst.
-
Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?
-
.filmor schrieb:
Hast du meinen Post denn nicht gelesen?
Es bringt dir absolut nichts, Unicode mit fester „Zeichenlänge“ zu speichern, da ein Unicode-Codepunkt eben nicht zwingend ein Zeichen geschweige denn ein Glyph ist. Der einzige „Vorteil“ ist, dass du dir keine ungültigen Zeichen durch unvorsichtiges abschneiden oder einfügen basteln kannst, aber das kann mit gewissenhafter Programmierung auch gut verhindert werden.
find etc. funktionieren natürlich auch mit UTF-8-Strings.Ich habe jetzt nochmal nachgeschaut. Unter Windows wird intern wohl UCS-2 als 16 Bit Unicode verwendet. Ich Zitiere mal aus der wikipedia, und hebe die Stelle hervor:
UCS-2 (2-byte Universal Character Set) is an obsolete character encoding which is a predecessor to UTF-16. The UCS-2 encoding form is nearly identical to that of UTF-16, except that it does not support surrogate pairs and therefore can only encode characters in the BMP range U+0000 through U+FFFF. As a consequence it is a fixed-length encoding that always encodes characters into a single 16-bit value. As with UTF-16, there are three related encoding schemes (UCS-2, UCS-2BE, UCS-2LE) that map characters to a specific byte sequence.
Jetzt sag mir bitte was ich falsch verstehe. Ich weiß selbst das UTF-X nicht zwangsweise 1 Buchstabe für eine Basiseinheit X hat, aber zumindestens unter bestimmten Betriebssystemen wird für die Verwendung in der UI etc. auf ein System mit einer fixen Breite umgewandelt. Und wenn ich weiterhin Windows als beispiel verwende, dient hier dieses System auch als Basis für die Strings unter .Net.
Mag sein das ich manches falsch verstanden habe, aber sollte ich mich hier irren, so wäre das falschen Informationen über eben diese Formate zuzuschreiben (ich bin beileibe kein Unicodeexperte, habe mich damit aber auch schon länger Beschäftigt und recherchiert).
Und wenn man in einen System arbeitet wo eine Fixe Länge definiert ist, so sag mir warum die Algorithmen nicht funktionieren sollten.
cu André
-
@asc es geht wohl eher darum, dass es nichts bringt, auf wchar_t kodierungen umzuschwenken(die normal 16Bit lang sind), um dann wieder daten zu verliereren(eben die surrogate pairs).
Mein Vorschlag:
std::basic_string<unsigned int,char_traits<unsigned int> > utf32string.
mit:
template <typename octet_iterator, typename u32bit_iterator> u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
aus der gelinkten utf8 lib. Das reicht zumindest, solange du nicht mit streams rumhantieren musst. ab dann wird es eh, egal welche kodierung, richtig ekelhaft. Wenn man bedenkt, dass es standardlibs ohne wchar_t implementierung gibt, wird einem ganz schwarz vor augen, mit einem für C++ völlig fremden Zeichensatz zu arbeiten.
-
Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.
-
.filmor schrieb:
Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?
Das ist ja ein extremer Aufwand, dann musst du jede Benutzereingabe, Konstante usw. zuerst nach UTF-8 Konvertieren. So gut wie keine Funktion gibt dir UTF-8 zurück, wenn du jetzt einmal zu konvertieren vergisst, dann hast du so nen dummen Fehler nach dem du ewig suchst.
-
.filmor schrieb:
Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.
Autsch. ok, da braucht man nen eigenen char type. langsam dämemrts mir, warum utf support als standard proposal abgelehnt wurde.
-
sososo schrieb:
.filmor schrieb:
Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?
Das ist ja ein extremer Aufwand, dann musst du jede Benutzereingabe, Konstante usw. zuerst nach UTF-8 Konvertieren. So gut wie keine Funktion gibt dir UTF-8 zurück, wenn du jetzt einmal zu konvertieren vergisst, dann hast du so nen dummen Fehler nach dem du ewig suchst.
Das ist im wesentlichen auch ein Punkt von mir.
Ich weiß das Unicode weit mehr als UCS-2 ist (Sorry, ich beschränke mich bei meinen Beispiel jetzt erstmal auf das System das ich kenne: Windows), aber nichts desto trotz wird man es ohnehin schwer haben in Bereichen die vom System nativ nicht abgedeckt werden sinnvoll zu arbeiten. Und innerhalb eines Systemes ist es durchaus ein möglicher 90% Weg, sich auf einen Kompromiss zu beschränken.
Ich hätte nichts dagegen wenn ich einen (möglichst portablen) Weg finde um mit UTF8 bis UTF-32 wirklich sinnvoll arbeiten zu können (Von dem Dateihandling bis zur UI), nur ist die sinnvolle Beschreibung wie man damit in Programmiersprachen gut umgeht entweder kaum vorhanden, oder es sind einfach zuviel Mülltreffer beim googlen um damit ernsthaft zu arbeiten. Sorry, ich erwarte das man nicht erst den ganzen Unicode-Standard durchackern muss um mit Unicode arbeiten zu können. Mich interessiert auch bei einem Container nicht die konkrete Umsetzung (auch wenn ich vielleicht den ein oder anderen schon selbst implementiert habe).
Das Problem liegt ja nicht nur bei C++ mit seiner mangelnden Unterstützung, sondern es gibt genügend andere Sprachen die wenn sie Unicode anbieten intern auch mit einem mehr oder weniger weitreichenden Kompromiss arbeiten.
cu André
-
Wo liegt denn das Problem? Die Kombinations„zeichen“ werden ja erst relevant, wenn man den Text tatsächlich rendern will und da muss man eh sukzessive Vorgehen (also ist's egal, ob man wahlfreien Zugriff hat), entsprechendes gilt für die meisten Parser. Normalisierungsroutinen sind nicht so schwer zu schreiben und abgesehen davon auch gut verfügbar. Mir fällt wirklich kein Fall ein, in dem ich Random-Access /und/ Unicode bräuchte …
otze schrieb:
.filmor schrieb:
Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.
Autsch. ok, da braucht man nen eigenen char type.
Eben nicht. UTF-8 in char ftw!
@asc: UCS-2 hilft dir da mal überhaupt nicht weiter. Die Combining Characters gibt's da auch. Mir geht's nicht um UTF-16, das ist eh total verkorkst, sondern um beliebige Fixed-Byte-Encodings für Unicode, also UTF-32 oder die UCS-2-Untermenge von UTF-16. Es nutzt einfach nichts.
-
Ja genial!
Jetzt folge ich nicht mehr mit Abstand, sondern ich renne ziellos durch die dunklen Gassen dieser was-auch-immer.....
Entschuldigt bitte, wenn ich jetzt immer noch nicht weiß, was ich machen kann und wenn ich nicht mehr viel verstanden habe.
Vielleicht könnt Ihr Euch gemeinsam auf Antworten zu 1-5 (siehe erste Seite) einigen, zumindest partiell?!
Im Prinzip möchte ich natürlich viele Sonderzeichen abdecken, aber wenigstens die dt. Umlaute und die Standards der verbreiteteren Sprachen wäre sinnig....hilfe!
-
IMHO solltest du für alles std::string mit UTF-8 benutzen (dokumentieren nicht vergessen ;)) und nur für den allerletzten Schritt die Umwandlung zu der geforderten Kodierung durchführen.
Aber die ist doch bei LPCTSTR gar nicht eindeutig, oder?
Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei. Wenn du Boost nicht verwenden möchtest kannst du einfach die utf8_codecvt_facet.hpp und die entsprechende .cpp-Datei nehmen, die benötigen AFAIK keine anderen Boost-Bibliotheken außer Boost.Config und davon kannst du den Code einfach rauswerfen (ist nur Präprozessorkram).
-
.filmor schrieb:
IMHO solltest du für alles std::string mit UTF-8 benutzen (dokumentieren nicht vergessen ;)) und nur für den allerletzten Schritt die Umwandlung zu der geforderten Kodierung durchführen.
Aber die ist doch bei LPCTSTR gar nicht eindeutig, oder?
Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei. Wenn du Boost nicht verwenden möchtest kannst du einfach die utf8_codecvt_facet.hpp und die entsprechende .cpp-Datei nehmen, die benötigen AFAIK keine anderen Boost-Bibliotheken außer Boost.Config und davon kannst du den Code einfach rauswerfen (ist nur Präprozessorkram).Aber wozu dieser ganze Aufwand, dass man überall an UTF-8 denken muss, wenn es am Schluss doch LPCTSTR also 16 bit Unicode wird?
Für wen soll den das Programm sein?
-
.filmor schrieb:
Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei.
Das ist kein encoding nach wchar_t, sondern einfach nach utf32:
utf8_codecvt_facet is a specialization of std::codecvt specifically designed to handle the case of translating between UTF-8 and UCS-4.