paedubucher hat geschrieben: 27.01.2019 09:48:15
EDIT 2: Bei à stimmt das erste, bei ¶ das zweite Byte überein:
Code: Alles auswählen
ö 11000011 10110110
à 11000011 10000011
¶ 11000010 10110110
Ich glaube, du verstehst das Problem noch nicht ganz.
Dein Beispiel hier ist komplett in der UTF-8-Welt. Das Problem kommt aber von einer unerlaubten Vermischung von Encodings, also vom Wechsel zwischen Encoding-Welten.
In erklaer's dir nochmal:
Auf der einen Seite gibt es schreibenden Code. Der soll ein ``ö'' schreiben. Er schreibt es UTF-8-kodiert. Folglich schreibt er folgende zwei Bytes: 0xC3 0xB6.
Auf der anderen Seite gibt es lesenden Code. Dieser denkt sich -- warum auch immer -- dass er Bytes die er liest am liebsten nach Latin1 dekodiert. Er liest 0xC3, schaut in der Latin1-Charset-Tabelle nach und findet an der Stelle 0xC3 das Zeichen ``Ã''. Dann liest er 0xB6, schaut nach und findet ``¶''.
Haette der lesende Code die Bytes im gleichen Encoding gelesen wie wie gespeichert worden sind, dann waere auch das Richtige wieder rausgekommen.
Hier ein Beispielprogramm, das das gleiche Prinzip mittels Unions in C demonstriert, sozusagen als technische Analogie:
Code: Alles auswählen
#include <stdio.h>
#include <string.h>
int
main()
{
union {
int i;
float f;
char s[4];
} u;
u.i = 15;
printf("read a stored int as int: %d\n", u.i);
printf("read a stored int as float: %f\n", u.f);
printf("read a stored int as string: %s\n", u.s);
printf("\n");
strncpy(u.s, "abc", sizeof(u.s));
u.s[sizeof(u.s)] = '\0';
printf("read a stored string as int: %d\n", u.i);
printf("read a stored string as float: %f\n", u.f);
printf("read a stored string as string: %s\n", u.s);
printf("\n");
u.f = 3.141592;
printf("read a stored float as int: %d\n", u.i);
printf("read a stored float as float: %f\n", u.f);
printf("read a stored float as string: %s\n", u.s);
return 0;
}
Sein Output (auf meinem System, denn wenn man falsche Typen rausliest ist das Ergebnis undefiniert):
Code: Alles auswählen
B-) make union
cc union.c -o union
B-) ./union
read a stored int as int: 123456
read a stored int as float: 0.000000
read a stored int as string: @
read a stored string as int: 6513249
read a stored string as float: 0.000000
read a stored string as string: abc
read a stored float as int: 1078530008
read a stored float as float: 3.141592
read a stored float as string: I@
B-)
Weniger technisch findest du das gleiche Problem dann, wenn jemand Spanisch schreibt und die andere Person Portugiesisch liest. Das funktioniert teilweise, weil die Sprachen verwandt sind (wie UTF-8 und Latin1 auch), aber an manchen Stellen versteht der Leser nur Quatsch, weil es ein diese spanischen Worte in Portugiesisch nicht gibt (das ist wie dein ``ö'' oder der Float als String gelesen) oder er versteht etwas Falsches (False Friends oder der Float als Int gelesen).
Du musst dir keine Bits anschauen. Es geht nur um die Interpretation von Bytes. Es geht um das Encoding, in dem geschrieben und gelesen wird. Dieses muss natuerlich das gleiche sein.
Man kann schon auch zwischen Encodings uebersetzen, aber das bedarf eines aktiven Vorgangs (d.h. ein Programm muss das tun). Beim Lesen von Daten aber muss immer das gleiche Encoding verwendet werden wie zum Schreiben verwendet wurde. Das ist eigentlich logisch. Bloss wird (wie bei der Union auch) nicht vermerkt, in welchem Encoding gespeichert worden ist. Das muss man halt irgendwie wissen. Wenn immer klar waere, wie etwas zu interpretieren waere, dann wuerde dein Problem gar nicht auftreten.
Ich hoffe, das konnte das Problem damit klarer machen.