Zeichensatzproblem mit mysqli_fetch_all

- mysqli
- php
- zeichencodierung
Hallo zusammen,
wenn ich in PHP 8.0.30 eine SQL-Abfrage mit mysqli_fetch_all($result, MYSQLI_ASSOC) abhole, werden im Ergebnis Umlaute mit ä angezeigt. Bei der Ausgabe in einer Schleife mit mysqli_fetch_assoc($result) wird wie erwartet ein ä angezeigt.
Weiß jemand, wieso das passiert? Ich konnte dazu nichts finden. Mir fällt es auch gerade zum ersten Mal auf.
Schöne Grüße
Nico
Hallo Nico R.,
typischer Fall von „kann ja gar nicht sein“. Zumindest dann nicht, wenn alle anderen Parameter gleich sind.
Die verwendete Zugriffsfunktion macht definitiv nicht den Unterschied.
Es sieht so aus, als würdest Du für das ä eine UTF-8 Bytesequenz haben, diese aber nicht als UTF-8, sondern als ISO 8859 ausgeben.
Es gibt unterschiedliche Einflussmöglichkeiten, die den Unterschied erzeugen. Wo genau der Einfluss ist, hängt sehr an deiner Anwendung. Die korrekte Implementierung ist heutzutage, dass die Datenbank, die Tabellen und die Character-Spalten utf8mb3 oder utf8mb4 verwenden, dass man seine PHP Scripte als UTF8 speichert und alle Zeichenketten, die Non-ASCII-Zeichen enthalten können (was so gut wie alle sind) mit mb_-Funktionen verarbeitet. Ist ein Baustein in einem Single-Byte Zeichensatz, drohen ständige Fehlinterpretationen der Codierung. Hier bleibt Dir nur, Stück für Stück zu analysieren, wo auf dem Weg das Encoding nicht das ist, das Du erwartest.
Rolf
Hallo Rolf,
ja, du hast recht, das war quatsch. Die Ursache liegt an einer anderen Stelle. Das kurzzeitige Nichtauftreten fiel nur zufällig mit dem Auskommentieren von mysqli_fetch_all zusammen.
Es sieht so aus, als würdest Du für das ä eine UTF-8 Bytesequenz haben, diese aber nicht als UTF-8, sondern als ISO 8859 ausgeben.
Es handelt sich um eine php-Datei, die ich per JS/fetch aufrufe. In der Testausgabe des Ergebnisses mit var_dump werden die Umlaute noch korrekt angezeigt. Aber wenn ich zusätzlich noch eine Testausgabe per echo mache, erscheinen dort die ä usw. Auch die Anzeige des var_dump ändert sich dann übrigens, das zeigt die Umlaute dann plötzlich ebenfalls nicht mehr an.
Findet hier durch das echo eventuell eine automatische Erkennung/Umschaltung statt? In der Antwort-Kopfzeile der PHP-Datei wird als content-type angezeigt: text/html; charset=UTF-8.
Ich werde wohl morgen noch etwas rumtesten. Zeichensätze sind so gaaar nicht mein Thema, bisher musste ich mich auch fast nie darum kümmern. Ich frage mich, was dieses Mal anders ist...
Schöne Grüße
Nico
n Abend,
Es handelt sich um eine php-Datei, die ich per JS/fetch aufrufe. In der Testausgabe des Ergebnisses mit var_dump werden die Umlaute noch korrekt angezeigt. Aber wenn ich zusätzlich noch eine Testausgabe per echo mache, erscheinen dort die ä usw.
das lässt mich vermuten, dass du zum Client (Browser) hin keine Angabe der Zeichencodierung machst und der Browser daher raten darf. Und der Browser rät "ISO/Latin", die Daten in der DB liegen auch in ISO/Latin vor, aber das PHP-Script ist in UTF-8 codiert.
Auch die Anzeige des var_dump ändert sich dann übrigens, das zeigt die Umlaute dann plötzlich ebenfalls nicht mehr an.
Passt zur These.
Findet hier durch das echo eventuell eine automatische Erkennung/Umschaltung statt? In der Antwort-Kopfzeile der PHP-Datei wird als content-type angezeigt: text/html; charset=UTF-8.
Das passt wiederum nicht zur These.
Einen schönen Tag noch
Martin
Hallo Nico R.,
content-type: text/html; charset=UTF-8.
Ich meine, das wäre in neueren PHP Versionen der Default, bzw. du gibst in der php.ini per default_charset
das Encoding an, dass es per Default verwenden soll, und der Default für diesen Schalter ist UTF-8.
Ich finde aber auch Empfehlungen, dass man diesen Header "sicherheitshalber" selbst setzen solle.
Du solltest versuchen, mit minimalen Scripten zu testen. Ohne DB Zugriff, konstante Daten. Irgendwas ist in deiner Runtime-Umgebung, das Einfluss hat. Machst Du vielleicht output-Buffering und die mb-Funktionen sind beteiligt? Da gibt es Autodetect-Features.
Und eine wichtige Frage ist auch noch: Wie ist das Encoding deines PHP Quellcodes? In dem Zusammenhang interessiert mich: gibst Du mit var_dump Daten aus der Datenbank aus, mit dem echo aber eine feste Zeichenkette im Sourcecode? Das würde für Encoding-Unterschiede zwischen DB und Source sprechen.
Rolf
Hallo Rolf, hallo Martin,
ich antworte jetzt mal nur hier. Ja, den content-type gebe ich (bisher) nicht explizit an. Es handelt sich um ein Script, das eigentlich gar nichts ausgeben soll, ich mache da nur eine testweise Ausgabe in der Konsole. Das Setzen von header('Content-Type: text/html; charset=UTF-8') hat darüber hinaus keine Veränderung gebracht.
Ich habe den Übeltäter aber inzwischen ausfindig gemacht. Daher hier nochmal ganz kurz und vereinfacht die Aufgabe des Scripts: Über ein Formular wird eine CSV-Datei per JS/fetch an das Script gesendet. Dort werden die Daten per fgetcsv() eingelesen, untersucht usw. und in der DB gespeichert.
Und genau die CSV-Datei (die nicht von mir kommt) ist das Problem. Wenn ich die in Notepad öffne, wird mir als Zeichencode ANSI angezeigt. Wenn ich die Daten beim Einlesen testweise mit mb_detect_encoding() in der Konsole anzeige, wird bei "normalem" Text ohne Umlaute ASCII angezeigt. Sobald ein Wert mit z.B. einem ä (bzw. hier ä) kommt, lautet die Anzeige UTF-8.
Nun sind ja in ASCII keine Umlaute enthalten. Deswegen vielleicht die automatische Umschaltung auf UTF-8, die dann aber nicht passt, weil die Daten als ANSI gespeichert sind? Wie kommt der Server überhaupt auf ASCII? Wie könnte ich erreichen, dass hier ANSI verwendet wird, so wie auch die CSV-Datei vorliegt?
Wenn ich die CSV-Datei in Notepad nach UTF-8 konvertiere und einlese, werden die Umlaute korrekt dargestellt. mb_detect_encoding() startet dann bei einfachen Strings nach wie vor mit ASCII, bei Strings mit Umlauten wird auch wieder automatisch auf UTF-8 umgeschaltet, das funktioniert dann aber in diesem Fall.
Sämtliche scriptseitigen Versuche mit mb_convert_encoding() und iconv() in verschiedenen Kombinationen haben erstmal keinen Erfolg gebracht. Wäre das überhaupt der richtige Ansatz?
Schöne Grüße
Nico
Hallo Nico R.,
Wie könnte ich erreichen, dass hier ANSI verwendet wird, so wie auch die CSV-Datei vorliegt?
Das wäre der erste Schritt. Hast Du für diese Hypothese klare Beweise gefunden?
Um das zu verifizieren, brauchst Du ein Hex-Dump Tool. Lade sie im Zweifelsfall hierhin hoch.
Wenn die CSV-Datei immer nur reines ASCII enthält (was bei Messdaten o.Ä. durchaus vorkommen kann), dann ist die Frage, wie Du sie speicherst, wurscht. Die Bytecodierung einer solchen Datei ist für ANSI und UTF-8 identisch (abgesehen von einem möglichen UTF-8 Byte Order Mark zu Beginn der Datei).
Rolf
Hallo Rolf,
Das wäre der erste Schritt. Hast Du für diese Hypothese klare Beweise gefunden?
Der Notepad zeigt wie gesagt unten ANSI an.
- Enthält die Datei überhaupt non-ASCII Zeichen (Zeichen mit Bytewert > 127)?
- Wenn ja, sind sie als ein Byte (ANSI) oder als zwei oder mehr Bytes (UTF-8) gespeichert?
Ich hab jetzt mal aus der Datei alle Zeichen bis auf ein ä gelöscht. Wenn ich das von ASCI zu HEX konvertiere, wird E4 angezeigt, das entspricht ja der ANSI-Tabelle.
Schöne Grüße
Nico
Hallo Nico R.,
gut, d.h. deine CSV Datei ist nachweislich ANSI. D.h. sie kommt auch als ANSI-Bytefolge am Server an. Die nimmst Du mit fgetcsv auseinander, und dann speicherst Du die gefundenen Daten in der Datenbank.
An dieser Stelle bin ich nicht ganz sicher, was die DB tut, insbesondere dann, wenn die Datenbankverbindung oder die DB-Objekte UTF-8 sind. Das müsstest Du überprüfen.
Wenn Du die Daten mit einer anderen Codierung an die DB sendest, als die Verbindungscodierung erfordert, können alle möglichen Unfälle passieren. Es kann gut sein, dass Du dann UTF-8 Bytefolgen in deinen DB-Tabellen stehen hast, und DAS ist eine Tretmine, die jederzeit hochgehen kann.
Wie schon gesagt: optimal ist, wenn Verbindung und DB-Objekte Unicode-fähig sind. MYSQL verwendet utf8mb3 (Codepoints 0-65535) oder utf8mb4 (voller Unicode). Du musst dann nur ANSI-codierte Daten erstmal in UTF-8 konvertieren, bevor Du sie in der Datenbank speicherst. Du bekommst sie UTF-8-codiert zurück, und kannst sie dann ohne weitere Konvertierung (von htmlspecialchars abgesehen) zum Browser schicken, weil Du im Content-Type ja UTF-8 als Charset angegeben hast. Für Stringoperationen musst Du dann auch die mb_-Funktionen verwenden, die klassischen Stringoperationen von PHP können bei Multibyte-Zeichencodierungen jederzeit Datenschrott erzeugen.
Rolf
Hallo Rolf,
entschuldige bitte. Es wäre noch wichtig gewesen, zu erwähnen, dass das Problem nicht bei der Speicherung in der DB auftritt, sondern schon vorher, bei der Verarbeitung der Daten. Im Gegenteil, in die DB wird im letzten Schritt sogar alles korrekt eingetragen.
Bei der Verarbeitung der CSV-Daten untersuche ich diese unter anderem mit similar_text(), um darauf basierend weitere Werte in die DB einzutragen. Durch die starke Abweichung bei Umlauten bekomme ich jetzt Ergebnisse, die nicht mehr passen.
Ich versuche das mal zu ordnen. Das Verhalten ist so verwirrend, dass ich selbst immer wieder durcheinander komme.
Ab hier wirds komplett verrückt. Sobald ich die CSV-Daten ohne utf8-encode() im Array_2 speichere, werden in var_dump(Array_1) die Umlaute falsch dargestellt, mit utf8-encode() erscheinen sie korrekt. Aber dieses var_dump wird eigentlich gleich zum Anfang ausgeführt. Ich frage mich, warum die viel spätere Speicherung der Daten in Array_2 Einfluss auf die Darstellung von Array_1 hat, und warum die überhaupt beeinflusst wird.
Und es wird nochmal verrückter. Wenn ich die Werte in Array_2 mit utf8-encode() speichere, wird wie gesagt Array_1 korrekt angezeigt. Wenn ich dann aber die Werte aus Array_2 mit echo probeweise ausgebe, werden die Umlaute in Array_1 plötzlich wieder falsch dargestellt. Nur wenn ich das echo mit utf8_decode() ausgebe, bleibt das Array_1 korrekt. Dann wird aber natürlich das echo selbst mit fehlerhaften Umlauten angezeigt 🤪
Ich bin hier irgendwie in eine utf8_encode/decode-Hölle hineingeraten. Vermutlich kann mir hier auch niemand helfen, ohne direkten Blick auf den Code. Und selbst dann... Naja, wenn ich eine Lösung gefunden habe, werde ich es euch wissen lassen.
... du kannst mittels mysqli_get_charset() abfragen, was verwendet wird.
Achja, das hat ["charset"]=> string(4) "utf8" ergeben. Das scheint also korrekt zu sein.
Schöne Grüße
Nico
Hallo Nico,
Sobald ich die CSV-Daten ohne utf8-encode() im Array_2 speichere, werden in var_dump(Array_1) die Umlaute falsch dargestellt, mit utf8-encode() erscheinen sie korrekt.
Das ist wirklich verrückt. Hier spielen weitere Effekte mit, die Du vermutlich für irrelevant hältst, die aber dennoch Einfluss haben.
Abfrage DB-Daten => Speicherung in Array_1 (Umlaute korrekt)
Einlesen CSV-Daten => Speicherung in Array_2 (Umlaute korrekt)
Quervergleich zwischen DB-Daten und CSV-Daten (Umlaute in Array_1 fehlerhaft)
Nein, das KANN nicht sein. Dass sie Daten in Array_1 durch einen Vergleich mittels similar_text verändert werden, schließe ich aus. Da passiert noch irgendwas anderes. Ich kann nicht beurteilen, ob deine Vorstellung von "korrekt" der Realität entspricht
Ich habe ein Testprogramm geschrieben:
<pre><?php
$utfmuell = "Müller";
$ansimuell = utf8_decode($utfmuell);
echo strlen($utfmuell) . " - " . bin2hex($utfmuell) . "\n";
echo strlen($ansimuell) . " - " . bin2hex($ansimuell) . "\n";
$db = [ "name" => $utfmuell ];
$csv = [ "name" => $ansimuell ];
var_dump($db);
var_dump($csv);
echo "Ähnlichkeit: " . similar_text($db['name'], $csv['name']);
var_dump($db);
var_dump($csv);
Die Codierung des PHP-Quellcodes ist UTF-8, deshalb erhalte ich mit utf8_decode($utfmuell) die ANSI-Version. Wenn man es genau nimmt, verwende ich hier eine missbilligte Funktion, utf8_decode verwendet ISO-8859-1 als Zeichensatz, der obsolet ist und durch ISO-8859-15 ersetzt wurde. Die Unterschiede sind aber marginal, und für mein Testprogramm liefern utf8_decode und iconv("UTF-8", "ISO-8859-15", $utfmuell) das gleiche.
Wenn ich das laufen lasse, erhalte ich:
Warning: Your output contains characters that could not be displayed.
7 - 4dc3bc6c6c6572
6 - 4dfc6c6c6572
array(1) {
["name"]=>
string(7) "Müller"
}
array(1) {
["name"]=>
string(6) "Mller"
}
Ähnlichkeit: 5
array(1) {
["name"]=>
string(7) "Müller"
}
array(1) {
["name"]=>
string(6) "Mller"
}
Die ANSI-ü erzeugen die Warnung, dass ungültige Zeichen in der Ausgabe wären, darum steht da Mller für die ANSI-Ausgaben. Dort, wo Müller in der Ausgabe steht, war ein UTF-8 String.
Also - da ändert sich nichts. Nicht in der Minimalversion.
Rolf
Hallo Rolf,
der entscheidende Teil fehlt bei dir. Der ist offenbar das Einlesen der ANSI-codierten CSV-Datei. Ich habs jetzt mal minimal reduziert nachgebaut. Das Phänomen tritt sogar schon ohne weitere Behandlung der Daten auf. Es genügt eine einfache Ausgabe.
Je nach Button wird Fetch-Datei 1 oder 2 geladen. Einziger Unterschied ist die Ausgabe der CSV-Daten. Wenn ich das var_dump() des csv_array deaktiviere, werden im db_array die Umlaute angezeigt, mit var_dump() nicht. Hier noch der PHP-Teil dazu:
if($csv = fopen("csv_upload.csv", 'r')) {
$db_array = array();
$db_array[] = "Schuster";
$db_array[] = "Müller";
$csv_array = array();
while(!feof($csv)) {
array_push($csv_array, fgetcsv($csv, null, ","));
}
echo "<h1>db_array</h1>";
echo "<pre>";
var_dump($db_array);
echo "</pre>";
echo "<h1>csv_array</h1>";
echo "<pre>";
// bei Deaktivierung korrekte Umlaut-Darstellung im db_array
var_dump($csv_array);
echo "</pre>";
}
Es scheint ja serverseitig eine Umschaltung der Codierung stattzufinden, sobald er registriert, dass in dem Script an irgend einer Stelle Nicht-UTF-codierte Daten dargestellt werden sollen. Das Setzen dieses headers hat keine Veränderung gebracht:
header('Content-Type: text/html; charset=utf-8');
Hier hätte ich erwartet, dass zwar das csv_array ohne Umlaute dargestellt wird, dafür aber das db_array korrekt. Aber nee, keene Änderung. Hat noch jemand eine Idee oder eine andere Erklärung?
Schöne Grüße
Nico
Hallo Nico,
das Einlesen hatte ich durch die Stringzuweisung simuliert.
Das Phänomen tritt sogar schon ohne weitere Behandlung der Daten auf. Es genügt eine einfache Ausgabe.
Nein. Wenn ich deine Seite aufrufe, sehe ich im Netzwerk-Tab:
csv_upload_fetch_1.php:
<h1>db_array</h1><pre>array(2) {
[0]=>
string(8) "Schuster"
[1]=>
string(7) "Müller"
}
</pre><h1>csv_array</h1><pre>array(3) {
[0]=>
array(1) {
[0]=>
string(6) "B�cker"
}
[1]=>
array(1) {
[0]=>
string(9) "Schlosser"
}
[2]=>
bool(false)
}
</pre>
csv_upload_fetch_2.php:
<h1>db_array</h1><pre>array(2) {
[0]=>
string(8) "Schuster"
[1]=>
string(7) "Müller"
}
</pre><h1>csv_array</h1><pre></pre>
Das sieht absolut okay und erwartungskonform aus.
Im "B�cker" steht \ufffd - das Unicode-Ersatzzeichen für ungültige Codepoints. Das könnte von PHP beim Ausgaben erzeugt worden sein. Bei mir ist das default_charset auf UTF-8 gesetzt, bei Dir auch?
Ich habe dein PHP auch bei mir lokal laufen lassen, mit deiner CSV Datei (die man ja downloaden kann) - gleiche Ausgabe.
Rolf
Hallo Rolf,
Nein. Wenn ich deine Seite aufrufe, sehe ich im Netzwerk-Tab:
csv_upload_fetch_1.php:
<h1>db_array</h1><pre>array(2) { [0]=> string(8) "Schuster" [1]=> string(7) "Müller" } </pre><h1>csv_array</h1><pre>array(3) { [0]=> array(1) { [0]=> string(6) "B�cker" } [1]=> array(1) { [0]=> string(9) "Schlosser" } [2]=> bool(false) } </pre>
Ich habs gerade mal im Chrome getestet, den verwendest du ja vermutlich. Dort sieht der Response in der Tat wie bei dir aus. Aber im Firefox steht dort:
db_array
array(2) { [0]=> string(8) "Schuster" [1]=> string(7) "Müller" }
csv_array
array(3) { [0]=> array(1) { [0]=> string(6) "Bäcker" } [1]=> array(1) { [0]=> string(9) "Schlosser" } [2]=> bool(false) }
Nun kommt beides am Ende aufs Gleiche raus. Ein String-Vergleich liefert wegen der fehlerhaften Umlaute jeweils nicht 100%. Ich hab die csv_upload_fetch_1.php jetzt mal um die Vergleichsfunktion erweitert:
if($csv = fopen("csv_upload.csv", 'r')) {
$db_array = array();
$db_array[] = "Schuster";
$db_array[] = "Bäcker";
$csv_array = array();
while(!feof($csv)) {
array_push($csv_array, fgetcsv($csv, null, ","));
}
echo "<h1>db_array</h1>";
echo "<pre>";
var_dump($db_array);
echo "</pre>";
echo "<h1>csv_array</h1>";
echo "<pre>";
var_dump($csv_array);
echo "</pre>";
for($i=0; $i<count($csv_array); $i++) {
for($j=0; $j<count($db_array); $j++) {
if(is_array($csv_array[$i])) {
similar_text(strtolower($csv_array[$i][0]), strtolower($db_array[$j]), $prozent);
echo $db_array[$j]." / ".$csv_array[$i][0]." = ".$prozent."<br>";
}
}
}
}
Das Ergebnis:
Schuster / Bäcker = 42.857142857143
Bäcker / Bäcker = 76.923076923077
Schuster / Schuster = 100
Bäcker / Schuster = 40
Wie könnte ichs hinbekommen, dass - egal welcher Browser zum Einsatz kommt - Bäcker mit Bäcker verglichen wird?
Bei mir ist das default_charset auf UTF-8 gesetzt, bei Dir auch?
In der Netzwerk-Konsole? Ja, sowohl im FF als auch im Chrome.
Schöne Grüße
Nico
Hallo zusammen,
Wie könnte ichs hinbekommen, dass - egal welcher Browser zum Einsatz kommt - Bäcker mit Bäcker verglichen wird?
ich habs hinbekommen. Auch wenn die Lösung möglicherweise nicht optimal ist, will ich sie der Vollständigkeit halber nicht vorenthalten:
...
$agent = $_SERVER['HTTP_USER_AGENT'];
if(str_contains($agent, "Firefox"))
$db = iconv('UTF-8', 'MS-ANSI', $db);
if(str_contains($agent, "Chrome") OR str_contains($agent, "Safari"))
$csv = iconv('MS-ANSI', 'UTF-8', $csv);
...
Wie schon in der Konsolenausgabe/Netzwerkanalyse zu sehen war, decodieren FF und Chrome offenbar unterschiedlich und verlangen entweder eine Konvertierung in die eine oder die andere Richtung. Keine Ahnung, ob das nur in meinem speziellen Fall so ist. In jedem Fall arbeitet die Vergleichsfunktion jetzt in beiden Browsern korrekt, hier die Ausgabe für den FF:
db_array
array(2) {
[0]=>
string(8) "Schuster"
[1]=>
string(7) "Bäcker"
}
csv_array
array(3) {
[0]=>
array(1) {
[0]=>
string(6) "Bäcker"
}
[1]=>
array(1) {
[0]=>
string(9) "Schlosser"
}
[2]=>
bool(false)
}
Schuster / Bäcker = 42.857142857143
Bäcker / Bäcker = 100
Schuster / Schlosser = 70.588235294118
Bäcker / Schlosser = 40
https://fsv-optik.de/tests/csv_upload.html
Schöne Grüße
Nico
Hallo Nico,
danke für die Rückmeldung. Das ist jedoch ein Workaround, keine Lösung. Vor allem ist nicht klar, weshalb der Workaround überhaupt funktioniert.
Im Fall des Firefox konvertierst Du die DB-Werte nach ANSI, behältst die ANSI-Werte aus der CSV-Datei und führst den Vergleich mit ANSI-Bytes/-Zeichen durch.
Im Fall von Chrome/Safari behältst Du die DB-Werte als UTF-8, konvertierst die CSV-Werte nach UTF-8 und führst den Vergleich mit UTF-8-Bytes/Unocide-Zeichen durch.
Wenn Du auf diese Weise weiterkommst, dann tu es, aber ich prophezeihe Dir, dass da unter der Oberfläche irgendein Drache haust, der nur darauf wartet, Feuer zu speien.
Rolf
Moin,
danke für die Rückmeldung. Das ist jedoch ein Workaround, keine Lösung. Vor allem ist nicht klar, weshalb der Workaround überhaupt funktioniert.
genau das ist der Grund, warum mich die "Lösung" auch nicht beruhigen würde. Solange ich das Problem nicht wirklich verstanden habe und dann eine "Lösung" finde, die nur zufällig funktioniert ... 🤔
Das ist wie: "Das Problem hat sich von selbst gelöst, aber ich weiß nicht warum."
Das ist für mich auch eher beunruhigend, weil das Problem dann jederzeit wieder auftreten könnte, solange ich nicht weiß, wo es herkommt.
Wenn Du auf diese Weise weiterkommst, dann tu es, aber ich prophezeihe Dir, dass da unter der Oberfläche irgendein Drache haust, der nur darauf wartet, Feuer zu speien.
Das fürchte ich auch.
"In jedem kleinen Problem steckt ein großes, das nur zu gern raus will."
(aus Murphy's Law)
Einen schönen Tag noch
Martin
Hallo,
Und genau die CSV-Datei (die nicht von mir kommt) ist das Problem. Wenn ich die in Notepad öffne, wird mir als Zeichencode ANSI angezeigt.
ja, weil der Windows-Editor nicht glaubt, dass überhaupt noch jemand ASCII verwendet und daher ANSI als "einfachste" Codierung vorschlägt. Wobei der das als Sammelbegriff für alle 1-Byte-Codierungen meint.
Wenn ich die Daten beim Einlesen testweise mit mb_detect_encoding() in der Konsole anzeige, wird bei "normalem" Text ohne Umlaute ASCII angezeigt.
PHP ist etwas archaischer: Wenn der Text keine Zeichen mit Codes oberhalb 0x7F enthält, ist ASCII eine gültige Aussage.
Sobald ein Wert mit z.B. einem ä (bzw. hier ä) kommt, lautet die Anzeige UTF-8.
Also kommt die CSV-Datei in UTF-8 codiert daher.
Nun sind ja in ASCII keine Umlaute enthalten. Deswegen vielleicht die automatische Umschaltung auf UTF-8, die dann aber nicht passt, weil die Daten als ANSI gespeichert sind?
Sind sie das wirklich?
Sämtliche scriptseitigen Versuche mit mb_convert_encoding() und iconv() in verschiedenen Kombinationen haben erstmal keinen Erfolg gebracht. Wäre das überhaupt der richtige Ansatz?
Auf jeden Fall erstmal sicher feststellen, welches Programm welche Codierung liefert. Dann überlegen: An welcher Stelle ist eine Konvertierung in UTF-8 am sinnvollsten? Und dann auch konsequent dabei bleiben.
Einen schönen Tag noch
Martin
Hallo Martin,
standardmäßig wird die CSV-Datei im Notepad mit "Encode in ANSI" angezeigt, die Umlaute werden dann korrekt dargestellt. Wenn ich auf "Encode in UTF-8" wechsle, wird statt ä ein xE4 angezeigt. Das spricht doch eigentlich dafür, dass es keine UTF-8-Datei ist, oder? 🤔
Schöne Grüße
Nico
@@Nico R.
Zeichensätze sind so gaaar nicht mein Thema
Sollten sie auch nicht sein. Es genügt zu wissen, dass dein Zeichensatz immer Unicode ist.
Und man sollte wissen, dass Zeichensatz etwas anderes ist als Zeichencodierung. Beides zu vermengen ist die Mutter aller Probleme mit Zeichen.
Und das wurde in der Vergangenheit leider von vielen vermengt. So kam es zur Abkürzung charset
, was eben nicht für Zeichensatz (character set) steht, sondern für Zeichencodierung. (Symbolbild)
Stoff zum Lesen:
🖖 Live long and prosper
Hallo Gunnar,
danke für die Links. Ein bisschen klarer ists mir schon geworden. Mal gucken, obs irgendwann klick macht.
Da ist dir bei UTF n kleiner Buchstabenrdeher reingerutscht. Oder soll das so? 🤔
Schöne Grüße
Nico
@@Nico R.
Da ist dir bei UTF n kleiner Buchstabenrdeher reingerutscht. Oder soll das so? 🤔
Meh, das sollte natürlich nicht so. Ich hab aber die Keynote-Datei nicht mehr, und im PDF krieg ich das wohl nicht mehr geändert?
Außerdem: Wenn ich das Slidedeck neu hochladen würde, würde zwar der URL zur Präsentation gleich bleiben, aber die URLs zu den einzelnen Slides (der #<hash>
-Teil) würden sich ändern. Ich glaub, ich lass das so.
🖖 Live long and prosper