Sebastian Becker: Sonderzeichen in externen Dateien

Hallo,

ich möchte eine externe Datei mit Metatags als reiner Text mit uncodierten deutschen und internationalen Sonderzeichen per PHP includieren.

In der Ausgabe werden die Sonderzeichen falsch oder gar nicht dargestellt. Zuerst hielt ich dies für eine Frage der Servereinstellungen. Dies hat sich aber nicht bestätigt, da das Problem auf drei verschiedenen Servern bei unterschidlichen Providern in gleicher Weise auftritt.

Die Mitgabe von HTTP-Headern hat leider auch nicht geholfen. Sobald ich den Text nicht includiere, sondern in die Ausgabedatei direkt hineinschreibe, wird er richtig dargestellt.

Hier bin ich jetzt mit meinem Latein am Ende. Die Aufgabenstellung ist ja eigentlich nicht so exotisch, als daß sie nicht tausendfach vorkäme - und dann kann es ja wohl nicht immer dasselbe Problem geben ...

Was mache ich falsch?

Danke für alle Hinweise, Grüße,

Sebastian

  1. Hello,

    Die Mitgabe von HTTP-Headern hat leider auch nicht geholfen.

    Musst Du dich wohl entscheiden, ob "includieren" oder mittels "passthrough" und Headern direct an den Client auszugeben, oder ggf. sogar dem Client nur die Referenz auf die Datei zu schicken...

    Harzliche Grüße vom Berg
    esst mehr http://www.harte-harzer.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. Hallo, Tom,

      Musst Du dich wohl entscheiden, ob "includieren" oder mittels "passthrough" und Headern direct an den Client auszugeben, oder ggf. sogar dem Client nur die Referenz auf die Datei zu schicken...

      Das ist mir jetzt zu abstrakt - erklär mal bitte näher was Du meinst.

      Aber wie schon gesagt: Es muß ja wohl auch mit "include" gehen - ich bin ja nicht der erste, der davon Gebrauch macht ...

      Any ideas?

      Grüße,

      Sebastian

  2. echo $begrüßung;

    ich möchte eine externe Datei mit Metatags als reiner Text mit uncodierten deutschen und internationalen Sonderzeichen per PHP includieren.

    Wenn du "uncodiert" sagst, meinst du sicherlich, dass du keine Entities dafür verwendet hast. Ansonsten gibt es kein "uncodiert" bei einer Text-Datei. Jedes Schriftzeichen wird durch einen bestimmten Code repräsentiert. Es gibt mehrere Systeme, Schriftzeichen zu einem Code zuzuordnen.
    Es gilt nun erst einmal herauszufinden, in welcher Kodierung das Dokument vorliegt. Das könnte beispielsweise ISO-8859-1 oder UTF-8 oder ... sein.
    Wenn du nicht weißt, in welcher Kodierung der Text vorliegt, bleibt dir nur zu Raten und zu Experimentieren. Das einfachste wird sein, den Text in einen Browser zu laden und dann durch Umstellen der Zeichenkodierung herauszufinden, welche die gewünschte Darstellung ergibt.

    Jetzt gilt es zu ermitteln, in welcher Kodierung die Dokumente vorliegen, in die du deine Texte einzubinden versuchst.
    Damit weißt du nun, welche Umwandlung du beim Einbinden gegebenenfalls verwenden musst.

    Die Mitgabe von HTTP-Headern hat leider auch nicht geholfen.

    Wenn du von der Kodierungsangabe (charset) im HTTP-Header sprichst, geht man i.A. davon aus, dass du die auch wirklich meinst. Diese Angabe in den HTTP-Headern hat nämlich Vorrang vor einer im HTML-<head> verwendeten http-equiv-Angabe eines <meta>-Tags. Letztere kommt zur Anwendung, wenn der Server keine Kodierungsangabe im HTTP-Header mitsendet, und auch wenn die Datei aus dem lokalen Dateisystem geöffnet wird. Ist keine der beiden Angaben vorhanden, darf/muss der Browser raten.

    echo "$verabschiedung $name";

    1. Hallo, dedlfix,

      danke für die Antwort.

      Wenn du "uncodiert" sagst, meinst du sicherlich, dass du keine Entities dafür verwendet hast.

      Genau ...

      Es gilt nun erst einmal herauszufinden, in welcher Kodierung das Dokument vorliegt. Das könnte beispielsweise ISO-8859-1 oder UTF-8 oder ... sein.

      Ich habe z.Zt. zu Testzwecken gar keine Kodierung angegeben. Die Angabe einer Kodierung ändert aber auch nichts an der Darstellung im Browser, denn die Zeichen werden ja schon serverseitig falsch ausgegeben (und zwar nur bei der Eibindung per include) ...

      Jetzt gilt es zu ermitteln, in welcher Kodierung die Dokumente vorliegen, in die du deine Texte einzubinden versuchst.
      Damit weißt du nun, welche Umwandlung du beim Einbinden gegebenenfalls verwenden musst.

      Ich habe die entsprechende Datei mit einem Texteditor (UltraEdit) erstellt - möglicherweise ist das Format UTF-8. Wie kann ich das überprüfen?

      Die Mitgabe von HTTP-Headern hat leider auch nicht geholfen.
      Wenn du von der Kodierungsangabe (charset) im HTTP-Header sprichst, geht man i.A. davon aus, dass du die auch wirklich meinst.

      Ich meine im Allgemeinen was ich sage, so auch in diesem Falle  ;-)  . Ich habe also einen header per PHP ausgegeben und zusätzlich einen HTML-Header - das hat aber nicht geholfen ...

      Vielleicht hängt das Phänomen mit den unzureichenden Unicode-Fähigkeiten von PHP zusammen?!

      Grüße,

      Sebastian

      1. echo $begrüßung;

        Es gilt nun erst einmal herauszufinden, in welcher Kodierung das Dokument vorliegt. Das könnte beispielsweise ISO-8859-1 oder UTF-8 oder ... sein.

        Ich habe z.Zt. zu Testzwecken gar keine Kodierung angegeben. Die Angabe einer Kodierung ändert aber auch nichts an der Darstellung im Browser, [...]

        Einfach irgendwas anzugeben ist nicht die Lösung. Davon springen die Bytes des Textes auch nicht um.
        Gehe davon aus, dass es nicht möglich ist, aus einer Folge von Bytes herauszulesen, wie diese richtig zu interpretieren sind.[*]
        Deine Daten liegen in einer bestimmten Kodierung vor. Genau diese musst du angeben, damit der Empfänger die Bytefolge der Daten gemäß dieser Kodierung dekodieren kann.

        Ich habe die entsprechende Datei mit einem Texteditor (UltraEdit) erstellt - möglicherweise ist das Format UTF-8. Wie kann ich das überprüfen?

        Durch Anschauen mit einem Nicht-Unicode-fähigen Editor. Dazu musst du aber wissen, wie so ein UTF-8 kodierter Text (im Speziellen die "unamerikanischen" Zeichen) aussieht, wenn du ihn mit der Standard-Kodierung deines Windows (ISO-8859-1-kompatibel) ansiehst, um ihn als solchen zu erkennen. Oder du öffnest, wie ich bereits sagte, die Datei im Browser und probierst es mit der dort vorhandenen händisch einstellbaren Kodierungsangabe.

        Vielleicht hängt das Phänomen mit den unzureichenden Unicode-Fähigkeiten von PHP zusammen?!

        Nein. Unicode-Fähigkeiten brauchst du nur, wenn du mit den Strings arbeiten möchtest. Zum Beispiel darf beim Zählen der Zeichen eines UTF8-Strings nicht einfach nur die Anzahl der Bytes herangezogen werden.
        Wenn es um das schlichte Durchreichen per include (oder mit readfile(), was mir in dem Fall besser geeignet scheint) geht, dann brauchts keine Unicode-Fähigkeiten.

        Ich vermute, dass du den einzubindenden Text (vielleicht durch Unachtsamkeit beim Speichern) nun in UTF-8-Kodierung vorliegen hast und dass die Seite, in die er eingebunden werden soll, in ISO-8859-1 vorliegt. Für der Fall gibt es keine korrekte Kodierungsangabe. Einer der beiden Teile ist dann immer falsch. Dann hilft beispielsweise, den Text nochmal in ISO-8859-1 (der Ultraedit sagt ASCII dazu) abzuspeichern (wird das beste sein), oder wie folgt mit PHP-Mitteln zu flickschustern: Einlesen des Textes in einen String z.B. mit file_get_contents(), Umwandeln nach ISO-8859-1 mit utf8_decode(), Ausgabe mit echo, Charset-Angabe in HTTP- und HTML-Header auf ISO-8859-1 stellen.

        echo "$verabschiedung $name";

        [*] Man kann zwar Rätselraten, doch kann die interpretierende Software das Ergebnis des Rateversuchs nicht mit der wirklichen Lösung vergleichen kann.

        1. Hallo, dedlfix,

          danke für die ausführliche und hilfreiche Antwort.

          Ich vermute, dass du den einzubindenden Text (vielleicht durch Unachtsamkeit beim Speichern) nun in UTF-8-Kodierung vorliegen hast und dass die Seite, in die er eingebunden werden soll, in ISO-8859-1 vorliegt. Für der Fall gibt es keine korrekte Kodierungsangabe. Einer der beiden Teile ist dann immer falsch. Dann hilft beispielsweise, den Text nochmal in ISO-8859-1 (der Ultraedit sagt ASCII dazu) abzuspeichern (wird das beste sein), oder wie folgt mit PHP-Mitteln zu flickschustern: Einlesen des Textes in einen String z.B. mit file_get_contents(), Umwandeln nach ISO-8859-1 mit utf8_decode(), Ausgabe mit echo, Charset-Angabe in HTTP- und HTML-Header auf ISO-8859-1 stellen.

          Letzteres ich mal versucht mit ...

          echo utf8_decode(file_get_contents('keywords.inc.php'));

          Das Ergebnis ist immer noch dasselbe ...

          Ich verzweifele bald ...

          Grüße,

          Sebastian

          1. echo $begrüßung;

            echo utf8_decode(file_get_contents('keywords.inc.php'));

            Das Ergebnis ist immer noch dasselbe ...

            Das sieht mir recht verkorkst aus. Am Anfang ist eine BOM (Byte Order Mark) zu sehen, aber von den Umlauten ist jede Kodierung verlorengegangen.
            Wenn ich mir die keywords.inc.php direkt ansehe, dann erhalte ich einen Text, den ich als ISO-8859-1 kodiert bezeichnen würde. Wenn man diesen als UTF-8 zu lesen und nach ISO-8859-1 umzuwandeln versucht geht das natürlich in die Hose.
            Was mich jetzt noch interessiert: Wo kommt die BOM her? Durch das utf8_decode() kommt sie nicht rein. Steht sie vielleicht in der includetest.php vor dem echo... ?
            Dein Server sendet übrigens keine Kodierungsangabe im HTTP-Header mit. Durch diese BOM versucht der Browser das Dokument als UTF-8 zu interpretieren. Und ob im weiteren Verlauf nun ISO-8859-1-kodierte oder verkorkste Umlaute gesendet werden spielt dann keine Rolle mehr. Beides liefert Datenmüll.

            Der Ultraedit zeigt in der Statuszeile rechts neben der Cursorposition an, welche Kodierung gerade verwendet wird. DOS/UNIX ist das Zeilenende-Verhalten und das U oder U8 davor wäre dann ein Unicode/UTF-8-Modus. Über Datei->Konvertieren kann man einiges umstellen.

            Meine Meinung: Wirf die BOM raus, stell alles auf ISO-8859-1 (UltraEdit: ASCII) um, wenn keine zwingenden Gründe für Unicode/UTF-8 vorliegen.

            echo "$verabschiedung $name";

            1. Hallo, dedlfix,

              echo utf8_decode(file_get_contents('keywords.inc.php'));
              Das Ergebnis ist immer noch dasselbe ...
              Das sieht mir recht verkorkst aus. Am Anfang ist eine BOM (Byte Order Mark) zu sehen, aber von den Umlauten ist jede Kodierung verlorengegangen.

              eine Byte Order Mark sehe ich zurzeit nicht - ich hatte das Phänomen aber auch schon ...

              Wenn ich mir die keywords.inc.php direkt ansehe, dann erhalte ich einen Text, den ich als ISO-8859-1 kodiert bezeichnen würde. Wenn man diesen als UTF-8 zu lesen und nach ISO-8859-1 umzuwandeln versucht geht das natürlich in die Hose.

              Das habe ich ja erst aufgrund Deiner Überlegungen gemacht - mit include() geht es aber wie gesagt genauso wenig.

              Was mich jetzt noch interessiert: Wo kommt die BOM her? Durch das utf8_decode() kommt sie nicht rein. Steht sie vielleicht in der includetest.php vor dem echo... ?

              Nein, da steht nichts außer ...

              // include 'keywords.inc.php';
              echo utf8_decode(file_get_contents('keywords.inc.php'));

              Ich setze die Kommentarzeichen jetzt wieder vor die erste Zeile.

              Dein Server sendet übrigens keine Kodierungsangabe im HTTP-Header mit. Durch diese BOM versucht der Browser das Dokument als UTF-8 zu interpretieren. Und ob im weiteren Verlauf nun ISO-8859-1-kodierte oder verkorkste Umlaute gesendet werden spielt dann keine Rolle mehr. Beides liefert Datenmüll.

              Das BOM ist möglicherweise der Knackpunkt - aber ich habe keine Ahnung, wo das herkommt. Am Server kann es entgegen meinen ersten Vermutungen eigentlich nicht liegen, da der Effekt bei drei verschiedenen Hostern auftritt.

              Der Ultraedit zeigt in der Statuszeile rechts neben der Cursorposition an, welche Kodierung gerade verwendet wird. DOS/UNIX ist das Zeilenende-Verhalten und das U oder U8 davor wäre dann ein Unicode/UTF-8-Modus. Über Datei->Konvertieren kann man einiges umstellen.

              Die Anzeige habe ich zwar nicht gefunden und das Umkodieren von UTF-8 nach ASCII hat nichts gebracht. Ich hatte übrigens vorher das File auch einmal mit Notepad abgespeichert - dann sollte Unicode eigentlich verloren gehen ...

              Meine Meinung: Wirf die BOM raus, stell alles auf ISO-8859-1 (UltraEdit: ASCII) um, wenn keine zwingenden Gründe für Unicode/UTF-8 vorliegen.

              Leichter gesagt als getan. Woher kommt nur diese blöde BOM???

              Grübelnde Grüße,

              Sebastian

            2. Hallo, dedlfix und alle anderen,

              so, jetzt habe ich meine beiden Files mit Dreamweaver neu abgespeichert - und siehe da, jetzt ist anscheinend alles in Ordnung. UltraEdit bzw. dessen Einstellungen war wohl die Ursache - wer hätte das gedacht?

              Jetzt ist also der Fehler im Prinzip beseitigt und damit kann ich jetzt erst mal beruhigt schlafen gehen ...

              Dennoch würde ich gerne wissen, woran die falsche Ausgabe gelegen hat - aus "akademischem" Interesse und vor allem damit ich in Zukunft keine Probleme mehr bekomme.

              In den UltraEdit-Voreinstellungen habe ich übrigens nichts Ungewöhnliches gefunden (Auto detect UTF-8 files ist on). Gibt es da noch irgendwelche kritischen Konfigurationsmöglichkeiten?

              Wenn ich jetzt die Inhalte des includetest.php-Files mit UltraEdit neu abspeichere, habe ich wieder den Effekt, daß nicht includierte Zeichen richtig und includierte falsch ausgegeben werden. Woran kann das liegen?

              Dankbar für alle sachdienlichen Hinweise, Grüße,

              Sebastian

              1. echo $begrüßung;

                so, jetzt habe ich meine beiden Files mit Dreamweaver neu abgespeichert - und siehe da, jetzt ist anscheinend alles in Ordnung. UltraEdit bzw. dessen Einstellungen war wohl die Ursache - wer hätte das gedacht?

                Der Ultraedit bringt es auch. Man kann da auf Hex-Darstellung umschalten, wobei man allerdings die UTF-8-BOM nicht sieht, da der UE intern mit 16 Bit pro Zeichen arbeitet und die BOM umwandelt.

                Jetzt ist also der Fehler im Prinzip beseitigt und damit kann ich jetzt erst mal beruhigt schlafen gehen ...

                Nicht wirklich. Der Server sendet immer noch keine Zeichensatzangabe und die BOM ist noch da. Nimm dir mal einen Firefox und installier da mal die LiveHTTPHeaders-Extension. Du kannst damit über das Kontext-Menü "Seiteninformationen anzeigen" lassen. Unter "Allgemein" findest du die Kodierung, die der FF grad verwendet. Unter "Header" findest du die "Antwort Header". Hinter "Content-Type" steht "text/html" jedoch ohne nachfolgende Kodierungsangabe. Mit Kodierungsangabe sähe das denn so aus: "text/html; charset=UTF-8". Die BOM kannst du erkennen, wenn du http://www.prinzhamlet.de/includetest.php aufrufst und über "Ansicht" -> "Zeichenkodierung" einmal "Westlich (ISO-8859-1)" einstellst. Du siehst dann am Anfang diese drei Zeichen "". Das ist die BOM. (Du siehst dann auch gleich noch, wie einige UTF-8-kodierte Umlaute aussehen, wenn man sie sich in ISO-8859-1 ansieht.)

                Dennoch würde ich gerne wissen, woran die falsche Ausgabe gelegen hat - aus "akademischem" Interesse und vor allem damit ich in Zukunft keine Probleme mehr bekomme.

                Wenn ich jetzt die Inhalte des includetest.php-Files mit UltraEdit neu abspeichere, habe ich wieder den Effekt, daß nicht includierte Zeichen richtig und includierte falsch ausgegeben werden. Woran kann das liegen?

                Was wird denn in der Statuszeile angezeigt? U8-DOS oder U-DOS oder DOS oder ...? Beim "Speichern unter" im UE kannst du einstellen, welches "Format" verwendet werden soll.
                Der Notepad ist im übrigen auch unicodefähig. Du siehst dort die BOM ebenfalls nicht. Im Notepad kann man auch beim Speichern ein bestimmte Kodierung angeben. Die BOM fügt er automatisch ein. Kleiner Test gefällig? Erstelle eine Datei und schreibe z.B. 5 Zeichen rein, ohne Umlaute und Zeilenumbruch. Speichere unter UTF-8 ab und schau im Explorer die Dateigröße an. Die dürfte nun 8 Bytes betragen.

                echo "$verabschiedung $name";