JavaScript, Bytes und Zeichen
Emil
- javascript
0 Der Martin0 Emil0 Emil
3 dedlfix
0 Antwort nicht angezeigt?
Lisa- zu diesem forum
Ein Eurozeichen besteht aus 3 Bytes mit den Wertigkeiten E2 82 AC. Wenn ich jedoch mit diesen Wertigkeiten die Bytes einzeln erzeuge und mit +=
aneinanderhänge erkennt JS das nicht als Eurozeichen sondern als 3 einzelne Zeichen. Was muss ich tun daß JS die aneinandergeängten Bytes als ein Zeichen, also das Eurozeichen erkennt?
MFG
Hallo,
Ein Eurozeichen besteht aus 3 Bytes mit den Wertigkeiten E2 82 AC.
in UTF-8 codiert, ja. In anderen Textcodierungen sieht es wieder völlig anders aus.
Wenn ich jedoch mit diesen Wertigkeiten die Bytes einzeln erzeuge und mit
+=
aneinanderhänge erkennt JS das nicht als Eurozeichen sondern als 3 einzelne Zeichen.
Korrekt. Weil Javascript seine eigenen interne Darstellung von Zeichen hat (Marc sagte neulich was von UTF-16, ich weiß es nicht besser). An die interne Codierung, die JS hier verwendet, kommst du aber meines Wissens nicht dran.
Was muss ich tun daß JS die aneinandergeängten Bytes als ein Zeichen, also das Eurozeichen erkennt?
Nicht auf Byte-Ebene arbeiten, sondern ein einzelnes Zeichen mit dem Code 0x20AC erzeugen.
Wenn du es unbedingt von der Byte-Ebene aus bearbeiten willst, kannst du die Byte-Sequenz auch selbst zum korrespondierenden Zeichencode verrechnen. Die Codierung als solche ist ja bekannt.
Viel Erfolg,
Martin
Wenn du es unbedingt von der Byte-Ebene aus bearbeiten willst, kannst du die Byte-Sequenz auch selbst zum korrespondierenden Zeichencode verrechnen. Die Codierung als solche ist ja bekannt.
Da wird mir nichts anderes übrigbleiben. MFG
Wenn du es unbedingt von der Byte-Ebene aus bearbeiten willst, kannst du die Byte-Sequenz auch selbst zum korrespondierenden Zeichencode verrechnen. Die Codierung als solche ist ja bekannt.
Da wird mir nichts anderes übrigbleiben.
Der Algorithmus ist ähnlich wie ein Deserializer. Hier ist er für PHP (gekürzt)
MFG
Tach!
Ein Eurozeichen besteht aus 3 Bytes mit den Wertigkeiten E2 82 AC.
in UTF-8 codiert, ja. In anderen Textcodierungen sieht es wieder völlig anders aus.
Wenn ich jedoch mit diesen Wertigkeiten die Bytes einzeln erzeuge und mit
+=
aneinanderhänge erkennt JS das nicht als Eurozeichen sondern als 3 einzelne Zeichen.
Wenn man das als \xE2\x82\xAC notiert, sind das keine Bytes sondern Zeichen.
Korrekt. Weil Javascript seine eigenen interne Darstellung von Zeichen hat (Marc sagte neulich was von UTF-16, ich weiß es nicht besser). An die interne Codierung, die JS hier verwendet, kommst du aber meines Wissens nicht dran.
Die interne Kodierung ist im Prinzip nicht weiter relevant. Man kommt damit üblicherweise nicht in Berührung. Vereinfacht kann man sagen, dass Javascripts String-Philosophie zeichenorientiert ist. Es arbeitet mit dem Zeichensatz Unicode und Kodierungen spielen normalerweise keine Rolle. Natürlich müssen die Zeichen in der Physik irgendwie kodiert werden, und es gibt auch einige Funktionen, die mit Kodierungen umgehen. Doch für das allgemeine Arbeiten mit Strings ist das nicht erforderlich.
Das versuchte ich Emil/hotti/pl schon mehrfach zu erklären, aber er weigert sich anscheinend beharrlich das anzunehmen und scheitert regelmäßig daran, wenn er sein Weltbild von Bytes auf Javascript überzustülpen versucht.
Was muss ich tun daß JS die aneinandergeängten Bytes als ein Zeichen, also das Eurozeichen erkennt?
Nicht auf Byte-Ebene arbeiten, sondern ein einzelnes Zeichen mit dem Code 0x20AC erzeugen.
Wenn du es unbedingt von der Byte-Ebene aus bearbeiten willst, kannst du die Byte-Sequenz auch selbst zum korrespondierenden Zeichencode verrechnen.
Eigentlich findet Zeichenkodierung außerhalb von Javascript statt. Der HTML-Parser dekodiert bereits den Datenstrom zu Zeichen, bevor es an Javascript übergeben wird.
Wenn man unbedingt mit Zahlen arbeiten möchte, gibt es String.fromCharCode()
und String.fromCodePoint()
zum Umwandeln. Aber das sind eben CodePoints, keine Bytes.
dedlfix.
Hallo dedlfix,
Die interne Kodierung ist im Prinzip nicht weiter relevant. Man kommt damit üblicherweise nicht in Berührung.
Die modifizierte Pilatus-Frage: Was ist üblich? Ist diese Aussage Westizismus? Etliche Ostasiatische Sprachen brauchen die Plane 1, um ihre Zeichen vollständig darstellen zu können. Für die sind JavaScript-Strings die Hölle, sie können die Funktionen von String.prototype nicht verwenden. Und wenn Dir irgendwer einen Unicode String wie 'de\u0301licieux' statt 'délicieux' vorwirft, steckst Du in der zusätzlichen Hölle der combining characters, selbst wenn Du in der BMP bleibst.
Unicode ist als 16-bit Code designed worden. JavaScript, Java und C# stammen aus dieser Zeit. Sie wollten modern und Unicode-fähig sein und haben die 16-bittige UCS-2 Codierung verwendet, sind aber von Unicode 3.1 überrollt worden.
Nachdem Unicode um die Planes 1-16 erweitert wurde und UTF-16 herauskam, musste JS um Codepoint-Funktionalität erweitert werden, das ist aber nur rudimentär mittels String.fromCodePoint und String.prototype.codePointAt erfolgt.
JavaScript und PHP haben da analoge Probleme. PHP Strings sind bytecodiert, funktionieren also nur mit Single-byte Codepages problemlos. Ein UTF-8 String in PHP benötigt die mb-Funktionen.
JavaScript-Strings waren ursprünglich UCS-2 codiert, d.h. ein BMP Zeichen ist einem 16-bit Wert (einem Charcode) zugeordnet. Mit Unicode 3.1 musste das auf UTF-16 umgedeutet werden, und die Zeichen der Planes 1-16 durch die entsprechenden Surrogat-Paare im Bereich D8-DF dargestellt werden.
Im Gegensatz zu PHP hat JavaScript aber keine mc-Funktionen (multicharcode Strings), man muss dafür eine passende Bibliothek verwenden, z.B. unistring. Die behandelt dann auch das spezielle Unicode-Problem der combining characters, z.B. 'e\u0301' vs 'é'.
Rolf
Tach!
Die interne Kodierung ist im Prinzip nicht weiter relevant. Man kommt damit üblicherweise nicht in Berührung.
Die modifizierte Pilatus-Frage: Was ist üblich? Ist diese Aussage Westizismus? Etliche Ostasiatische Sprachen brauchen die Plane 1, um ihre Zeichen vollständig darstellen zu können. Für die sind JavaScript-Strings die Hölle, sie können die Funktionen von String.prototype nicht verwenden. Und wenn Dir irgendwer einen Unicode String wie 'de\u0301licieux' statt 'délicieux' vorwirft, steckst Du in der zusätzlichen Hölle der combining characters, selbst wenn Du in der BMP bleibst.
Diese Probleme löst man aber auch nicht, indem man mit Bytes hantiert. Das muss Javascript nachbessern.
dedlfix.
Die interne Kodierung ist im Prinzip nicht weiter relevant. Man kommt damit üblicherweise nicht in Berührung.
Doch kommt man: In dem Moment wenn man Stringfunktionen anwendet. MFG
Tach!
Die interne Kodierung ist im Prinzip nicht weiter relevant. Man kommt damit üblicherweise nicht in Berührung.
Doch kommt man: In dem Moment wenn man Stringfunktionen anwendet.
Sehr allgemein und nichtssagend. Magst du genauer werden und erklären, warum man nicht umhinkommen soll?
dedlfix.
Programmieraufgaben sind vielfältig. Stell Dir vor Du bekommst ein Array mit Zahlen die Bytewertigkeiten darstellen. Gesucht sind die sich daraus ergebenden Codepoints. Ein Beispiel für den Kontextwechsel von Bytesemantic zu Charactersemantic. MFG
Tach!
Programmieraufgaben sind vielfältig. Stell Dir vor Du bekommst ein Array mit Zahlen die Bytewertigkeiten darstellen. Gesucht sind die sich daraus ergebenen Codepoints. Ein Beispiel für den Kontextwechsel von Bytesemantic zu Charactersemantic.
Das ist ein konkreter Anwendungsfall, noch dazu ein sehr spezieller, aber kein Beleg dass deine allgemeine Aussage allgemeine Gültigkeit hätte.
dedlfix.
Tach!
Programmieraufgaben sind vielfältig. Stell Dir vor Du bekommst ein Array mit Zahlen die Bytewertigkeiten darstellen. Gesucht sind die sich daraus ergebenen Codepoints. Ein Beispiel für den Kontextwechsel von Bytesemantic zu Charactersemantic.
Das ist ein konkreter Anwendungsfall, noch dazu ein sehr spezieller, aber kein Beleg dass deine allgemeine Aussage allgemeine Gültigkeit hätte.
Stringfunktionen sind z.b. upper(), lower(). Sie verändern nicht Zeichen sondern Bytes. Sie sind sozusagen eine API weil sie zwischen Zeichenorientierung und Byteorientierung vermitteln. Das sollte ein Programmierer zumindestens wissen. Diese Funktionen gibt es in allen PLs
MFG
Tach!
Stringfunktionen sind z.b. upper(), lower(). Sie verändern nicht Zeichen sondern Bytes.
'中文 español Deutsch'.toUpperCase()
ergibt "中文 ESPAÑOL DEUTSCH"
und arbeitet meiner Ansicht nach nicht auf Bytes, sondern weiß, welche Zeichen großgeschrieben werden können und welche bleiben müssen.
dedlfix.
Tach!
Stringfunktionen sind z.b. upper(), lower(). Sie verändern nicht Zeichen sondern Bytes.
'中文 español Deutsch'.toUpperCase()
ergibt"中文 ESPAÑOL DEUTSCH"
und arbeitet meiner Ansicht nach nicht auf Bytes, sondern weiß, welche Zeichen großgeschrieben werden können und welche bleiben müssen.
Groß- und Kleinbuchstaben haben nicht nur unterschiedliche Bytes sondern sogar unterschiedliche Codepoints. MFG
Tach!
Stringfunktionen sind z.b. upper(), lower(). Sie verändern nicht Zeichen sondern Bytes.
'中文 español Deutsch'.toUpperCase()
ergibt"中文 ESPAÑOL DEUTSCH"
und arbeitet meiner Ansicht nach nicht auf Bytes, sondern weiß, welche Zeichen großgeschrieben werden können und welche bleiben müssen.Groß- und Kleinbuchstaben haben nicht nur unterschiedliche Bytes sondern sogar unterschiedliche Codepoints.
Die Frage war, wie das auf Zeichen passt, die keine Buchstaben sind, oder anderweitig nicht für Groß-/Kleinschreibung infrage kommen.
Wenn man zeichenorientiert arbeitet, muss man nur wissen, welche Zeichen die passenden Gegenstücke für die Umwandlung sind. Bytes braucht man dazu nicht.
dedlfix.
@@dedlfix
'中文 español Deutsch'.toUpperCase()
ergibt"中文 ESPAÑOL DEUTSCH"
und arbeitet meiner Ansicht nach nicht auf Bytes
Natürlich nicht.
sondern weiß, welche Zeichen großgeschrieben werden können und welche bleiben müssen.
Ja, aber das weiß nicht so ganz, durch welche großen Zeichen ersetzt werden muss. String.toLocaleUpperCase()
weiß das.
Nur dass ß zu SS anstatt zu ẞ wird … Gibt’s da eine Locale-Angabe, die zum großen ẞ führt?
LLAP 🖖
Tach!
sondern weiß, welche Zeichen großgeschrieben werden können und welche bleiben müssen.
Ja, aber das weiß nicht so ganz, durch welche großen Zeichen ersetzt werden muss.
String.toLocaleUpperCase()
weiß das.
Noch ein Indiz, das Bytes keine Rolle spielen, sondern das anhand von Zeichen und auch Kontext (hier Sprache) entschieden werden muss.
Nur dass ß zu SS anstatt zu ẞ wird … Gibt’s da eine Locale-Angabe, die zum großen ẞ führt?
Also, sowohl .toUpperCase()
als auch .toLocaleUpperCase('DE')
macht daraus korrekt 'SS'. 😛
dedlfix.
@@dedlfix
Nur dass ß zu SS anstatt zu ẞ wird … Gibt’s da eine Locale-Angabe, die zum großen ẞ führt?
Also, sowohl
.toUpperCase()
als auch.toLocaleUpperCase('DE')
macht daraus korrekt 'SS'. 😛
😡
BTW: kein Dank an Apple, die meine Aussage mal eben ins Gegenteil verkehren.
LLAP 🖖
Hallo Gunnar,
mal ein Minus für dich, für Apple-Bashing ohne erkennbaren Sinn.
Rolf
@@Rolf B
mal ein Minus für dich, für Apple-Bashing ohne erkennbaren Sinn.
Die Kritik daran, dass in der Apple-Systemschrift das Zeichen ẞ mal einfach so durch SS ersetzt wird, ist für Dich Bashing?
Wie würdest du es finden, wenn eine Schrift die Zeichen Ro mal einfach so durch U ersetzt, Ulf?
LLAP 🖖
Hallo Gunnar,
mir ist nicht klar, warum das ein Apple-Problem sein soll. Dieser Chrome hier unter Windows macht's genauso, Edge und Fuchs auch.
Es ist übrigens egal, ob ich als Locale de-DE, DE oder en-US angebe. "Fuß" wird immer zu "FUSS" statt "FUẞ". Laut Duden, bzw. amtlichem Regelwerk ist FUSS nicht falsch (D160.2, §25 E3), sondern sogar eher noch "richtiger". Der Text nennt es als den Normalfall, und sagt, dass "FUẞ" auch möglich ist.
Ich verstehe, dass Du gerne "FUẞ" statt "FUSS" sehen willst. Ich kann Dir leider nur den Workaround anbieten, vor dem toLocaleUpperCase noch einen .replace("ß", "ẞ") zu machen. Kannst ja String.prototype mit einem Polyfill patchen.
Ulf
@@Rolf B
mir ist nicht klar, warum das ein Apple-Problem sein soll. Dieser Chrome hier unter Windows macht's genauso, Edge und Fuchs auch.
Nein. Es geht hier nicht mehr um JavaScript (String.toUpperCase()
/ String.toLocaleUpperCase()
), sondern um Apples System-Schriftart San Francisco.
In dieser Schriftart gibt es keine Glyphe für das Zeichen ẞ (großes ß); es wird durch Doppel-S ersetzt (OpenType-Feature).[1]
Obwohl ich in meinem Tweet das große ẞ verwendet hatte, wird auf Apple-Geräten, wo San Francisco verwendet wird, SS angezeigt (Screenshot) – und dadurch die Aussage meines Tweets entstellt.
Jetzt klarer? Du hattest „BTW“ überlesen?
Nochmal zurück zu String.toUpperCase()
/ String.toLocaleUpperCase()
:
Laut Duden, bzw. amtlichem Regelwerk ist FUSS nicht falsch (D160.2, §25 E3)
Bei der amtlichen Schreibung von Namen ist es falsch, ß durch SS zu ersetzen.
LLAP 🖖
So wird’s vermutlich gemacht. Denkbar wäre auch: es gibt eine Glyphe fürs große ẞ, die genauso aussieht wie zwei S. Glaub ich aber nicht. ↩︎
Hallo Gunnar,
Jetzt klarer?
Ja. Diese Information war für mich aus den Tweets nicht erkennbar, und mangels Apple Gerät auch nicht nachvollziehbar.
Du hattest „BTW“ überlesen?
Nein. Aber mangels Kontextinformation nicht kapiert.
Dass eine Opentype-Schrift ẞ in SS wandelt, ist schon ärgerlich. Ob Windows-Fonts das auch tun?
Update: Mit Notepad keinen gefunden. Kann an Notepad liegen - bei einigen Fonts wurde das ẞ nicht im gewählten Font, sondern in irgendwas sans-serifigem dargestellt.
Rolf
Hallo,
Jetzt klarer?
Ja. Diese Information war für mich aus den Tweets nicht erkennbar, und mangels Apple Gerät auch nicht nachvollziehbar.
mir ging es genauso. ich habe deinen Tweet nicht verstanden.
Gruß
Jürgen
Programmieraufgaben sind vielfältig. Stell Dir vor Du bekommst ein Array mit Zahlen die Bytewertigkeiten darstellen. Gesucht sind die sich daraus ergebenden Codepoints. Ein Beispiel für den Kontextwechsel von Bytesemantic zu Charactersemantic. MFG
PS: Falls Du eine Herausforderung suchst, gegeben ist
[65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
Gesucht ist die Lösung in JS (Kodierung ist UTF-8). MFG
Tach!
PS: Falls Du eine Herausforderung suchst, gegeben ist
[65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
Such ich nicht. Aber da das kein Javascript ist, nehme ich an das ist serverseitiger Code und dann nähme ich die Mittel der dortigen Programmiersprache, um daraus einen String zu erzeugen. Falls der zum Client muss, würde ich vermutlich JSON verwenden. Somit hätte ich kein Problem in Javascript mit Bytes zu hantieren.
dedlfix.
PS: Falls Du eine Herausforderung suchst, gegeben ist
[65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
Such ich nicht. Aber da das kein Javascript ist, nehme ich an das ist serverseitiger Code
Nein es ist JavaScript. Und ja, es gibt auch Lösungen in JavaScript, das ist die Aufgabe. MFG
Tach!
PS: Falls Du eine Herausforderung suchst, gegeben ist
[65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
Such ich nicht. Aber da das kein Javascript ist, nehme ich an das ist serverseitiger Code
Nein es ist JavaScript. Und ja, es gibt auch Lösungen in JavaScript, das ist die Aufgabe.
Ach ja, mein Fehler. Es sind ja Zahlen und deshalb nicht unter der Syntax zu Stringliteralen zu finden, wo ich schaute. Wie auch immer, das Hantieren mit Bytes würde ich dem Server überlassen wollen.
dedlfix.
Tach!
PS: Falls Du eine Herausforderung suchst, gegeben ist
[65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
Such ich nicht. Aber da das kein Javascript ist, nehme ich an das ist serverseitiger Code
Nein es ist JavaScript. Und ja, es gibt auch Lösungen in JavaScript, das ist die Aufgabe.
Ach ja, mein Fehler. Es sind ja Zahlen und deshalb nicht unter der Syntax zu Stringliteralen zu finden, wo ich schaute. Wie auch immer, das Hantieren mit Bytes würde ich dem Server überlassen wollen.
Ne, wir ziehen das jetzt mit JS durch! Du selbst warst derjenige der genau wissen wollte wie die Aufgabenstellung lautet. Hier ist sie!
MFG
Tach!
Ne, wir ziehen das jetzt mit JS durch! Du selbst warst derjenige der genau wissen wollte wie die Aufgabenstellung lautet. Hier ist sie!
Die sieht mir unvollständig aus, das kann nur ein Teilaspekt der Aufgabe sein. An der eigentlichen Aufgabe würde ich anzusetzen versuchen, nicht in das Problem zu laufen.
Ansonsten:
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
const text = new TextDecoder().decode(new Uint8Array(bytes))
dedlfix.
Tach!
Ne, wir ziehen das jetzt mit JS durch! Du selbst warst derjenige der genau wissen wollte wie die Aufgabenstellung lautet. Hier ist sie!
Die sieht mir unvollständig aus, das kann nur ein Teilaspekt der Aufgabe sein. An der eigentlichen Aufgabe würde ich anzusetzen versuchen, nicht in das Problem zu laufen.
Ansonsten:
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4]; const text = new TextDecoder().decode(new Uint8Array(bytes))
Da kommen keine Codepoints dabei raus. MFG
Tach!
Ansonsten:
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4]; const text = new TextDecoder().decode(new Uint8Array(bytes))
Da kommen keine Codepoints dabei raus.
Dann nimm noch codePointAt()
dazu.
dedlfix.
Tach!
Ansonsten:
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4]; const text = new TextDecoder().decode(new Uint8Array(bytes))
Da kommen keine Codepoints dabei raus.
Dann nimm noch
codePointAt()
dazu.
text.length ist ja schon falsch. Denn es sind 6 Codepoints, nicht 7. Genauso falsch wie @rolf b Lösung. TextDecoder() ist wohl ein experimentelles Feature. MFG
Tach!
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4]; const text = new TextDecoder().decode(new Uint8Array(bytes))
Da kommen keine Codepoints dabei raus.
Dann nimm noch
codePointAt()
dazu.text.length ist ja schon falsch. Denn es sind 6 Codepoints, nicht 7.
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
dedlfix.
Tach!
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4]; const text = new TextDecoder().decode(new Uint8Array(bytes))
Da kommen keine Codepoints dabei raus.
Dann nimm noch
codePointAt()
dazu.text.length ist ja schon falsch. Denn es sind 6 Codepoints, nicht 7.
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
In UTF-8 gibt es keine Surrogate. Und der Codepoint U+DFC2 ist falsch bzw, zuviel im Ergebnis. Diese 6 Codepoints müssen rauskommen: 41 42 43 1D7C2 20AC E4
MFG
Tach!
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
In UTF-8 gibt es keine Surrogate. Und der Codepoint U+DFC2 ist falsch bzw, zuviel im Ergebnis. Diese 6 Codepoints müssen rauskommen: 41 42 43 1D7C2 20AC E4
Genauer gesagt, in UTF-8 werden sie nicht benötigt. Nichtsdestotrotz kann man diese Codepoints in UTF-8 kodieren. Und in deinen Daten ist eben die UTF-8-Sequenz für den genannten Codepoint drin.
Aber zu "In UTF-8 gibt es keine Surrogate" passt "(Kodierung ist UTF-8)" nicht. Du müsstest mal deine UTF-8-Sequenz korrekt erstellen oder die Logik in deinen Aussagen überprüfen.
dedlfix.
Prüfe selbst und das ist mit Perl berechnet, da ist auch die richtige Byte-Sequenz.
Unter richtiger Anwendung des Kodierungsalgorithmus für UTF-8 kommt auch mit JS dasselbe raus. Wie schon mehrfach geschrieben, man muss den Algorithmus, den man selbstverständlich auch in JS umsetzen kann, nur richtig anwenden dann stimmt auch das Ergebnis. MFG
Tach!
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
In UTF-8 gibt es keine Surrogate. Und der Codepoint U+DFC2 ist falsch bzw, zuviel im Ergebnis. Diese 6 Codepoints müssen rauskommen: 41 42 43 1D7C2 20AC E4
Genauer gesagt, in UTF-8 werden sie nicht benötigt. Nichtsdestotrotz kann man diese Codepoints in UTF-8 kodieren. Und in deinen Daten ist eben die UTF-8-Sequenz für den genannten Codepoint drin.
Aber zu "In UTF-8 gibt es keine Surrogate" passt "(Kodierung ist UTF-8)" nicht. Du müsstest mal deine UTF-8-Sequenz korrekt erstellen oder die Logik in deinen Aussagen überprüfen.
Ich ziehe diese Aussagen zurück, hab nicht genau genug hingeschaut.
dedlfix.
@@dedlfix
text.length ist ja schon falsch. Denn es sind 6 Codepoints, nicht 7.
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
?? So würde ich das nicht sagen. Es sind 6 Zeichen, wovon eins nicht aus der MBP ist.
String.length
zählt nicht die Zeichen, sondern die UTF-16 code units. [MDN]
text.length; // 7
Array.from(text).length; // 6
[...text].length; // 6
JavaScript has a Unicode problem (Mathias Bynens)
LLAP 🖖
@@dedlfix
text.length ist ja schon falsch. Denn es sind 6 Codepoints, nicht 7.
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
?? So würde ich das nicht sagen. Es sind 6 Zeichen, wovon eins nicht aus der MBP ist.
String.length
zählt nicht die Zeichen, sondern die UTF-16 code units. [MDN]text.length; // 7 Array.from(text).length; // 6 [...text].length; // 6
Funktioniert aber auch nicht richtig. Die berechneten 6 CodePoints sind falsch. D.h., der falsch CP ist noch drin und der Letzte fehlt. MFG
@@Emil
Funktioniert aber auch nicht richtig. Die berechneten 6 CodePoints sind falsch. D.h., der falsch CP ist noch drin und der Letzte fehlt.
??
Wie auch schon in Rolfs Testausgabe sind die 6 Codepoints richtig.
for (character of text)
{
console.log(character, character.codePointAt());
}
ergibt:
"A" 65
"B" 66
"C" 67
"𝟂" 120770
"€" 8364
"ä" 228
LLAP 🖖
Tach!
Funktioniert aber auch nicht richtig. Die berechneten 6 CodePoints sind falsch. D.h., der falsch CP ist noch drin und der Letzte fehlt.
??
Wie auch schon in Rolfs Testausgabe sind die 6 Codepoints richtig.
Nee, er hat auch den kaputten mit drin.
for (character of text) { console.log(character, character.codePointAt()); }
ergibt:
... das richtige Ergebnis, weil die Zeichen vereinzelt und für sich betrachtet werden. .codePointAt()
auf den String angewendet (wie bei Rolf) kommt durcheinander.
dedlfix.
@@dedlfix
Wie auch schon in Rolfs Testausgabe sind die 6 Codepoints richtig.
Nee, er hat auch den kaputten mit drin.
Ähm ja, ich ziehe diese Aussage zurück, hab nicht genau genug hingeschaut. 😉
LLAP 🖖
Ich empfehle 1000 m Freistil (bin dann mal weg). MFG
Ich empfehle 1000 m Freistil (bin dann mal weg). MFG
Im ins Schwimmen zu kommen, eignet sich Freistil ganz hervorragend! MFG
Ich empfehle 1000 m Freistil (bin dann mal weg). MFG
Im ins Schwimmen zu kommen, eignet sich Freistil ganz hervorragend! MFG
Du, ich hab das alles neu lernen müssen. Anfangs, nach einer vorübergehenden Lähmung nur einarmig. War damals nicht einfach über Wasser zu bleiben. Von daher ist auch heute noch eine 50m Bahn dabei die ich komplett mit einem Arm kraule. Damit die Erinnerung bleibt. Und so langsam kommt auch die Beinarbeit wieder. Ohne Fleiß kein Preis! MFG
Tach!
Es sind 6 sichtbare und das Zeichen U+DFC2 aus dem Low-Surrogates-Bereich zwischen 𝟂 und €.
?? So würde ich das nicht sagen. Es sind 6 Zeichen, wovon eins nicht aus der MBP ist.
Ah jetzt ja. Wenn man das richtig dekodiert, dann muss da sowas rauskommen:
Bytes | CodePoint |
---|---|
65 | 41 |
66 | 42 |
67 | 43 |
F0 9D 9F 82 | 1D7C2 |
E2 82 AC | 20AC |
C3 A4 | E4 |
Auch text.codePointAt(4)
greift auf das halbe 1D7C2 zu.
JavaScript has a Unicode problem (Mathias Bynens)
Historisch bedingte Altlasten. Das auszubügeln würde wohl mehr kaputtmachen.
dedlfix.
Historisch bedingte Altlasten. Das auszubügeln würde wohl mehr kaputtmachen.
Dazu müsste man erstmal wissen daß man reingetappt und das Ergebnis falsch ist. MFG
Hallo dedlfix,
P.S. Die Tabellensyntaxdokumentation ist veraltet und ich kenne die neue Syntax nicht.
Keine Tabelle ohne Kopf
|A|B|
|---|---|
|5|7|
A | B |
---|---|
5 | 7 |
Ich pass die Hilfeseite an.
Bis demnächst
Matthias
@@Matthias Apsel
P.S. Die Tabellensyntaxdokumentation ist veraltet und ich kenne die neue Syntax nicht.
Keine Tabelle ohne Kopf […]
Ich pass die Hilfeseite an.
Die Postings im Archiv auch, die jetzt unlesbar sind? Wie dieses zum Beispiel? (Bug 79)
LLAP 🖖
Hallo Gunnar Bittersmann,
Ja.
Bis demnächst
Matthias
@@Matthias Apsel
Ja.
Danke. Hast du das jetzt für alle Archivpostings gemacht, die davon betroffen sind?
LLAP 🖖
Hallo Gunnar Bittersmann,
Danke. Hast du das jetzt für alle Archivpostings gemacht, die davon betroffen sind?
Nein, nur für jenes. Ich weiß ja nicht, welche Beiträge betroffen sind.
Bis demnächst
Matthias
@@Matthias Apsel /cc @Christian Kruse
Hallo Gunnar Bittersmann,
Danke. Hast du das jetzt für alle Archivpostings gemacht, die davon betroffen sind?
Nein, nur für jenes. Ich weiß ja nicht, welche Beiträge betroffen sind.
Eben.
Es ist vielleicht nicht die beste Idee, die Forumsoftware so zu änderen, dass vormals vorhandene und von Autoren verwendete Features nicht mehr funktionieren. Das betrifft u.a. Tabellen und LaTeX.
Wenn sich was ändert, sollte eine Migration vorhandener Inhalte automatisch stattfinden, sodass diese weiterhin lesbar sind.
LLAP 🖖
text.length ist ja schon falsch. Denn es sind 6 Codepoints, nicht 7. Genauso falsch wie @rolf b Lösung. TextDecoder() ist wohl ein experimentelles Feature.
TextDecoder arbeteitet trotzdem richtig. Wie Gunnar schon schrieb, ist die length-Eigenschaft von JS kaputt.
const bytes = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
const text = new TextDecoder().decode(new Uint8Array(bytes));
const codePoints = [...text].map(c => c.codePointAt(0).toString(16));
// ["41", "42", "43", "1d7c2", "20ac", "e4"]
TextDecoder, -Encoder ist eine gute Idee. Es enspricht dem Perlmodul Encode, was genauso gehandhabt wird. Somit erfolgt die Vermittlung zwischen Zeichenorientierung und Byteorientierung in JS nach denselben Prinzipien wie das in Perl seit Jahrzehnten üblich ist zwischen Zeichen und Bytes zu vermitteln.
In PlainJS sieht der Algorithmus UTF-8-Kodierung so aus:
function decode_utf8( aChars, nIdx ){
if( nIdx == null) nIdx = 0;
var nLen = aChars.length, nPart = aChars[nIdx];
this.cps = this.cps != null ? this.cps : [];
this.offs = this.offs != null ? this.offs : nIdx;
var cp = 0;
if( nPart > 251 && nPart < 254 && nIdx + 5 < nLen ){
// 6 bytes
cp = (nPart - 252) * 1073741824 + (aChars[nIdx + 1] - 128 << 24) + (aChars[nIdx + 2] - 128 << 18) + (aChars[nIdx + 3] - 128 << 12) + (aChars[nIdx + 4] - 128 << 6) + aChars[nIdx + 5] - 128;
this.cps.push(cp.toString(16).toUpperCase());
this.offs += 6;
}
else if( nPart > 247 && nPart < 252 && nIdx + 4 < nLen ){
// 5 bytes
cp = (nPart - 248 << 24) + (aChars[nIdx + 1] - 128 << 18) + (aChars[nIdx + 2] - 128 << 12) + (aChars[nIdx + 3] - 128 << 6) + aChars[nIdx + 4] - 128;
this.cps.push(cp.toString(16).toUpperCase());
this.offs += 5;
}
else if( nPart > 239 && nPart < 248 && nIdx + 3 < nLen ){
// 4 bytes
cp = (nPart - 240 << 18) + (aChars[nIdx + 1] - 128 << 12) + (aChars[nIdx + 2] - 128 << 6) + aChars[nIdx + 3] - 128;
this.cps.push(cp.toString(16).toUpperCase());
this.offs += 4;
}
else if( nPart > 223 && nPart < 240 && nIdx + 2 < nLen ){
// 3 bytes
cp = (nPart - 224 << 12) + (aChars[nIdx + 1] - 128 << 6) + aChars[nIdx + 2] - 128;
this.cps.push(cp.toString(16).toUpperCase());
this.offs += 3;
}
else if( nPart > 191 && nPart < 224 && nIdx + 1 < nLen ){
// 2 bytes
cp = (nPart - 192 << 6) + aChars[nIdx + 1] - 128;
this.cps.push(cp.toString(16).toUpperCase());
this.offs += 2;
}
else{
// 1 byte
this.cps.push(nPart.toString(16).toUpperCase());
this.offs += 1;
}
if( this.offs < nLen) examine(aChars, this.offs);
return this.cps;
}
.
Hallo Emil,
Für alle Browser mit Fetch API:
let a = [65, 66, 67, 0xF0, 0x9D, 0x9F, 0x82, 0xE2, 0x82, 0xAC, 0xC3, 0xA4];
new Response(new Uint8Array(a)).text()
.then(function(result) {
console.log(result);
let p=0;
while (true) {
let c = result.codePointAt(p);
if (c === undefined) break;
console.log(c);
p++;
}
console.log("String enthält " + p + " Codepoints");
});
Ausgabe:
ABC𝟂€ä
65
66
67
120770
57282
8364
228
String enthält 7 Codepoints
Mit for...of ließe sich die Schleife kompakter machen, aber String.prototype[@@iterator] fehlt in vielen Browsern.
Rolf
Nein es sind nich 7 sondern 6 Codepoints, Du hast da irgendwo noch einen Fehler drin. MFG
Hallo Emil,
da hast Du wohl recht. Das kommt davon, wenn man sich drauf verlässt, dass eine codePoint-Funktion Codepoints zählt.
JavaScript hat ein Unicode-Problem.
Rolf
In Perl erfolgte die Unicodeunterstützung auch nicht über Nacht. Da gab es viele fehlerhafte Subversionen.
MFG
Seit es die FileAPI für JS gibt und JS mit Binaries umgehen kann (ArrayBuffer, Blob, File usw.) ist das schon relevant (seit ein paar Jahren übrigens). Den Kontextwechsel von Zeichenorientierung zu Byteorientierung implementieren die Programmiersprachen unterschiedlich.
Fakt jedoch ist, daß dieser Kontextwechsel unabhängig von Programmiersprachen existiert. Denn eine Kodierung gilt nur innerhalb eines Programmes, sobald Daten das Programm verlassen, etwa um sie zu speichern, ist die interne Kodierung auszuschalten.
MFG
Hallo Lisa,
die Antwort von Dedlfix wird nicht angezeigt. Fehler im System?
Nein. Löschung.
LG,
CK
Hallo,
Nein. Löschung.
vermutlich durch dedlfix selbst. Das Wesentliche ist wohl in seiner Antwort von 10:51 enthalten.
Gruß
Kalk
Hallo
Nein. Löschung.
vermutlich durch dedlfix selbst. Das Wesentliche ist wohl in seiner Antwort von 10:51 enthalten.
dedlfix ist auch bei seinen Antworten contextsensitiv. 😀
Gruß
Jürgen