Fabian Transchel: serialize will (manchmal) nicht...

Hallo Forum,

ich habe ein Problem mit meinem Debian-Apachen (einmal Apache 1.3.20 mit PHP 4.1.2 und einmal Apache 2.0.x mit PHP 4.3),
er weigert sich beharrlich, mehrdimensional serialisierte Arrays wieder zu deserialisieren. Um das zu verdeutlichen das Testscript, was es bei mir nicht tut:

<schnipp>

<?php
$fp = fopen("homepage/guestbook.gb","r");
$daten = fread($fp,filesize("homepage/guestbook.gb"));
#echo($daten); //Bishier hin stimmt alles, die Datne werden richtig eingelesen, und sind korrekt. Unterm Win-Apachen wird genau dieser String auch unserialisiert, hier nicht...

echo("<br><br><br><pre>");
$guestdaten = unserialize($daten);
echo $guestdaten; //hier müsste "array" ausgegeben werden, wird aber nicht. Auch print_r() schweigt sich aus.
echo("</pre>");

$string = "daten, daten, daten";
$ergeb = serialize($string);
echo $ergeb;  //Geht.
$daten = unserialize($ergeb);
echo $daten; //Hier Funktioniert alles, das wird richtig serialisiert und auch wieder unserialisiert. Ist aber auch nur ein String, obwohl ich mich frage, was es damit zu tun hat...
?>
<hr>
<?php
$arrayeins[] = "1";
$arrayeins[] = "depp";
$arrayeins[] = "quark";
$arrayeins[] = "suppe";
$arrayeins[] = "serialize!"; //Ich erzeuge ein primitives, _ein_dimensionales Array.
$arr = serialize($arrayeins);
echo $arr; //Geht.
?>
<hr>
<?php
print_r(unserialize($arr)); //Geht auch.
?>

</schnapp>

Könnte es daran liegen, dass Windows und Linux verschiedene Zeilenenden verwenden? Ich greife hier auf Daten auf einer Winpartition zu.

Fabian

  1. Halihallo Fabian

    [...]

    Könnte es daran liegen, dass Windows und Linux verschiedene Zeilenenden verwenden? Ich greife hier auf Daten auf einer Winpartition zu.

    Ich kann mir den Fehler nur an dieser Stelle ausdenken.

    aus http://www.php.net/manual/en/function.fopen.php :
       Note: The mode may contain the letter 'b'. This is useful only on systems which
       differentiate between binary and text files (i.e. Windows. It's useless on Unix).
       If not needed, this will be ignored. You are encouraged to include the 'b' flag
       in order to make your scripts more portable.

    der (De)Serializer von PHP verwendet wohl auch eine binäre Repräsentation der Daten und
    könnte somit auf unterschiedlichen Systemen durchaus zu Fehlern führen, wenn man die
    Daten nicht im binmode einliest. Verwende also mal das Flag 'b'.
    Die anderen Tests, welche du ausführst, verwenden eine InMemory Variable, welche
    natürlich von diesem systemabhängigen Zeug nicht beeindruckt wird; deshalb verlaufen die
    Tests auch ohne Probleme. Öffnest du jedoch eine Datei und liest die Dateien ein, dann
    kann es wie genannt zum Problem führen.
    Würde mich interessieren, falls es daran gelegen hat.

    Viele Grüsse

    Philipp

    1. Hi

      [...]
      der (De)Serializer von PHP verwendet wohl auch eine binäre Repräsentation der Daten und
      könnte somit auf unterschiedlichen Systemen durchaus zu Fehlern führen, wenn man die
      Daten nicht im binmode einliest. Verwende also mal das Flag 'b'.

      Tut nix, hätte ich auch nicht gedacht, da es im Windows auch ohne geht. Ich denke, es könnte daran liegen, dass der Win-serializer ein anderes Umbruchformat verwendet hat, dass der Unix-de-serializer nicht mag.

      Die anderen Tests, welche du ausführst, verwenden eine InMemory Variable, welche
      natürlich von diesem systemabhängigen Zeug nicht beeindruckt wird; deshalb verlaufen die
      Tests auch ohne Probleme. Öffnest du jedoch eine Datei und liest die Dateien ein, dann
      kann es wie genannt zum Problem führen.

      Klar, so weit komme ich auch. Die Frage ist nur, _wo_ der Konflikt im Filesystem liegt... und wie man ihn beheben kann.

      Würde mich interessieren, falls es daran gelegen hat.

      Hat's nicht.

      Fabian

      1. Halihallo Fabian

        [...]
        der (De)Serializer von PHP verwendet wohl auch eine binäre Repräsentation der Daten und
        könnte somit auf unterschiedlichen Systemen durchaus zu Fehlern führen, wenn man die
        Daten nicht im binmode einliest. Verwende also mal das Flag 'b'.
        Tut nix, hätte ich auch nicht gedacht, da es im Windows auch ohne geht. Ich denke, es könnte daran liegen, dass der Win-serializer ein anderes Umbruchformat verwendet hat, dass der Unix-de-serializer nicht mag.
        Klar, so weit komme ich auch. Die Frage ist nur, _wo_ der Konflikt im Filesystem liegt... und wie man ihn beheben kann.

        Nun, in den letzten paar PHP-Versionen hat sich auch was an den Serializern geändert.
        Könnte es sein, dass du zum Deserialize eine andere Version als zum serialisieren
        verwendet hast? - Könnte sein, dass der neue/alte deserializer eben nicht mit dem
        neuen/alten Serializer zurecht kommt.
        Dein Verdacht, dass sich der Win-Serializer vom Unix-one unterscheidet halte ich zwar
        für sehr unwahrscheinlich, aber durchaus möglich.

        Viele Grüsse

        Philipp

        1. Hi

          Nun, in den letzten paar PHP-Versionen hat sich auch was an den Serializern geändert.
          Könnte es sein, dass du zum Deserialize eine andere Version als zum serialisieren
          verwendet hast?

          Ja, das ist tatsächlich der Fall.

          • Könnte sein, dass der neue/alte deserializer eben nicht mit dem neuen/alten Serializer zurecht kommt.
            Dein Verdacht, dass sich der Win-Serializer vom Unix-one unterscheidet halte ich zwar
            für sehr unwahrscheinlich, aber durchaus möglich.

          Ich habe gerade auf der PHP-Manual Seite den Hinweis gesehen, man solle serialisierte Strings mit add|stripslashes() behandeln, das könnte ein Anhaltspunkt sein. Meinst du wirklich, dass die verschiedenen Serialize-Versionen nicht untereinander kompatibel sind?

          Fabian

          1. Halihallo Fabian

            • Könnte sein, dass der neue/alte deserializer eben nicht mit dem neuen/alten Serializer zurecht kommt.
              Dein Verdacht, dass sich der Win-Serializer vom Unix-one unterscheidet halte ich zwar
              für sehr unwahrscheinlich, aber durchaus möglich.
              Ich habe gerade auf der PHP-Manual Seite den Hinweis gesehen, man solle serialisierte Strings mit add|stripslashes() behandeln, das könnte ein Anhaltspunkt sein. Meinst du wirklich, dass die verschiedenen Serialize-Versionen nicht untereinander kompatibel sind?

            Naja, es waren keine "grundlegenden" Änderungen. Folglich bleibt das "Grundgerüst", wie
            z. B. Arrays immer vorhanden und gleich. Ich sah auch gerade, dass die interne
            Repräsentation der Daten ziemlich einfach (ich meine damit textuell, nicht als
            Bytestring) umgesetzt wird, das senkt die Anfälligkeit für dieses Zeilenumbruchsproblem,
            was wir dachten.
            Wegen dem Versionskonflikt:
            Mit Sicherheit kann ich dir dies jedoch nicht sagen. Aber du kannst es selber mal
            versuchen; du hast ja wahrscheinlich noch die "Datenstruktur" für dein guestbook; setzte
            es mal in beiden Versionen um und vergleiche den Output; wenn er sich unterscheidet hast
            du verloren *g*.
            Dieser Versionskonflikt ist auf jeden Fall das einzige, was ich mir noch als
            Fehlerquelle denken kann...

            Viele Grüsse

            Philipp

          2. Hi nochmal

            Ich habe gerade auf der PHP-Manual Seite den Hinweis gesehen, man solle serialisierte Strings mit add|stripslashes() behandeln, das könnte ein Anhaltspunkt sein.

            Genau das war es. Man muss, wenn man serialisierte Strings speichert (was man naturgemäß damit tut), _nach_ dem serialisieren addslashes() benutzen, und nach dem auslesen aus dem Speichermedium (ob DB oder Textfiles ist herzlich egal) muss man stripslashes() anwenden, und _danach_ unserialize um die Daten zu behalten. Man, darauf muss man erstmal kommen, zum Glück gibt's ja das Manual, und da war Gott sei Dank ein Tipp, den ich schon 50 mal überlesen haben muss ;-))

            Fabian