Tarquinio: Array in Datei schreiben

Hallo ihrs.

Ich hab ein Problem und keine Lösung gefunden.
Könnt ihr mir verraten wie ich einen Array in eine datei schreiben kann? Allerdings ist in der Datei schon etwas drinne, also soll er die Datei einfach überschreiben.
Ausserdem sollte er für jedes Feld des Arrays eine neue Zeile anfangen damit ich die Datei später wieder mit file() auslesen kann.

Wie funktioniertn sowas? Ich hoffe ihr könnt mir helfen.

MfG
Tarquinio

  1. Hallo Tarquinio,

    Könnt ihr mir verraten wie ich einen Array in eine datei schreiben kann? Allerdings ist in der Datei schon etwas drinne, also soll er die Datei einfach überschreiben.

    Also, dann musst Du die Datei so öffnen:

    $fp = fopen ('dateiname', 'w');

    Das 'w' bewirkt, dass die Datei - falls sie schon existiert - komplett geleert wird.

    Ausserdem sollte er für jedes Feld des Arrays eine neue Zeile anfangen damit ich die Datei später wieder mit file() auslesen kann.

    Mittels $string = join ("\n", $array); kannst Du den Array in eine Zeichenkette verwandeln, die durch Zeilenende-Zeichen "\n" getrennt ist. Falls die Felder schon auf "\n" aufhören, also bereits Zeilenende-Zeichen enthalten, dann solltest Du stattdessen $string = join ("", $array); anwenden, sonst sind hinterher hinter jeder Zeile zwei Zeilenende-Zeichen, also werden lauter Leerzeilen eingefügt..

    Mittels fwrite ($fp, $string); kannst Du die Zeichenkette in die Datei schreiben.

    Und mittels fclose ($fp); kannst Du die Datei nun schließen.

    Viele Grüße,
    Christian

    1. Hello,

      Könnt ihr mir verraten wie ich einen Array in eine datei schreiben kann? Allerdings ist in der Datei schon etwas drinne, also soll er die Datei einfach überschreiben.

      Also, dann musst Du die Datei so öffnen:

      $fp = fopen ('dateiname', 'w');

      Das gilt aber nur dann, wenn niemand anderes zur selben Zeit Zugriff auf die Datei hat. Sonst gibts Knoten...

      Der einzig praktikable Öffnungsmodus für shared Files ist unter Berücksichtigung des dämlichen advisory Lockings "a+" mit anschließendem Locking und Positíonierung des Dateizeigers.

      Liebe Grüße aus http://www.braunschweig.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      1. Hallo Tom,

        Der einzig praktikable Öffnungsmodus für shared Files ist unter Berücksichtigung des dämlichen advisory Lockings "a+" mit anschließendem Locking und Positíonierung des Dateizeigers.

        Es fehlen 'Tarquinio' allerdings anscheinend einige Grundlagen und ich halte es für durchaus gerechtfertigt, erst einmal eine suboptimale Lösung anzubieten, solange sie verständlich ist.

        Aber Du bist gerne eingeladen, einen Feature Artikel zu File Locking mit PHP zu schreiben. ;-)

        Viele Grüße,
        Christian

        1. Hello,

          Es fehlen 'Tarquinio' allerdings anscheinend einige Grundlagen und ich halte es für durchaus gerechtfertigt, erst einmal eine suboptimale Lösung anzubieten, solange sie verständlich ist.

          Dann solltest Du das aber fairerweise auch mit dem Zusatz "eine sicher verbesserungsewürdige Lösung" kennzeichnen.

          Aber Du bist gerne eingeladen, einen Feature Artikel zu File Locking mit PHP zu schreiben. ;-)

          Ja, das hatte ich sowieso vor, allerdings unter dem Titel: "Arbeiten mit Flatfiles unter PHP". Wir haben die Musterläsungen schon fast fertig. Sind so ca. drei bis vier Schwierigkeitsgrade.

          Es entsteht dann schlussendlich ein include-Modul (prozedural), dann man einfach einbindet, einen Fileheader deklariert und Zugriffsrechte festlegt. Der Rest geht "von allein".

          Wie bekomm ich denn den Artikel in die passende Form?

          Liebe Grüße aus http://www.braunschweig.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          1. Hallo Tom,

            Dann solltest Du das aber fairerweise auch mit dem Zusatz "eine sicher verbesserungsewürdige Lösung" kennzeichnen.

            Ja, da hast Du Recht, ich werde das das nächste Mal dazuschreiben.

            Wie bekomm ich denn den Artikel in die passende Form?

            http://aktuell.de.selfhtml.org/sonst/layoutvorgaben.htm
            http://aktuell.de.selfhtml.org/sonst/sprachvorgaben.htm

            Viele Grüße,
            Christian

            1. Hallo!

              Sind so ca. drei bis vier Schwierigkeitsgrade.

              was soll mir das sagen ohne Skala? ;-)

              Wie bekomm ich denn den Artikel in die passende Form?

              http://aktuell.de.selfhtml.org/sonst/layoutvorgaben.htm
              http://aktuell.de.selfhtml.org/sonst/sprachvorgaben.htm

              Und hier gibt es noch eine Vorlage: http://aktuell.de.selfhtml.org/artikel/beitrag.htm#a3

              Grüße
              Andreas

              1. Hi!

                Und hier gibt es noch eine Vorlage: http://aktuell.de.selfhtml.org/artikel/beitrag.htm#a3

                Ach ja - und nichts an selfhtml@teamone.de schicken(kommt nicht an), lieber jemand passendes in dieser Liste suchen: http://aktuell.de.selfhtml.org/people/devs.htm

                Grüße
                Andreas

              2. Hallo Andreas,

                Und hier gibt es noch eine Vorlage: http://aktuell.de.selfhtml.org/artikel/beitrag.htm#a3

                Die ist AFAIK veraltet, zumindest nicht an die Layoutrichtlinien angepasst.

                Viele Grüße,
                Christian

      2. Hi
        Ich bin aber der einzige der auf die Datei zugreift.

        Danke, es hat gefunzt. Vielen Dank

        MfG
        Tarquinio

      3. Hallo Tom!

        Könnt ihr mir verraten wie ich einen Array in eine datei schreiben kann? Allerdings ist in der Datei schon etwas drinne, also soll er die Datei einfach überschreiben.

        Also, dann musst Du die Datei so öffnen:

        $fp = fopen ('dateiname', 'w');

        Das gilt aber nur dann, wenn niemand anderes zur selben Zeit Zugriff auf die Datei hat. Sonst gibts Knoten...

        Der einzig praktikable Öffnungsmodus für shared Files ist unter Berücksichtigung des dämlichen advisory Lockings "a+" mit anschließendem Locking und Positíonierung des Dateizeigers.

        Und was bringt das? Und wieso nicht "w"?

        Ich hatte mal das Problem dass ich "unique-ids" erzeugen wollte. Das Locking von PHP funktioniert auch - wenn alle sich an die Spielregeln halten, nicht 100%ig. Es ist zwar sehr unwahrscheinlich - aber möglich dass ein 2. Prozess Zurgiff auf die Datei erlangt, zwischen einem fopen und einem flock. Und wenn ich in so eine Textdatei eine unique-id schreibe, dann ist das recht doof wenn dann auf einmal 2 Prozesse von derselben Zahl ausgehen, und rein zufällig die selbe ID erzeugen ;)

        Für mich war die einzige Lösung damals - Verwendung einer externen Lock-Datei. Das heißt prinzipiell:

        fopen($file_lock)
        flock(LOCK_EX)

        fopen($file_unique_id)
          fputs
          fclose

        flock(LOCK_UN)
        fclose

        Weitere Möglichkeit íst zum Sperren einfach irgendeine Datei nehmen, das heißt immer wen gesperrt ist bestimmte Datei in "gesperrt" umbenennen, und danach wieder zurück... oder solche Späße halt.

        Kann man das mit Deine Methode komplett umgehen? Bedenke nur dass ich in diesem Fall an die Daten in der Datei unbedingt dran muss, und zwischen Lesen und Schreiben muss die Datei geschützt sein.

        Grüße
        Andreas

        1. Hello,

          Also, dann musst Du die Datei so öffnen:

          $fp = fopen ('dateiname', 'w');

          Das gilt aber nur dann, wenn niemand anderes zur selben Zeit Zugriff auf die Datei hat. Sonst gibts Knoten...

          Der einzig praktikable Öffnungsmodus für shared Files ist unter Berücksichtigung des dämlichen advisory Lockings "a+" mit anschließendem Locking und Positíonierung des Dateizeigers.

          Und was bringt das? Und wieso nicht "w"?

          Es könnte noch ein Lesezugriff dazwischenkommen. Ein w oder w+ zerstört im Moment des Öffnesn die Datei. Da könnte also jemand, der gearde vorher mit (r) geöffent hat, nun plötzlich ins Leere greifen.

          Daher immer die nichtzerstörende Öffnungsmethode benutzen und dann est lesen oder schreiben, wenn eine exclusive Sperre erfolgreich war.

          Liebe Grüße aus http://www.braunschweig.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          1. Hi Tom!

            Es könnte noch ein Lesezugriff dazwischenkommen.

            Was bei einem Counter der unique-IDs erzeugen soll natürlich fatal sein kann.

            Ein w oder w+ zerstört im Moment des Öffnesn die Datei.

            "zerstört"? in wiefern? Oder meinst Du auf '' setzen?

            Daher immer die nichtzerstörende Öffnungsmethode benutzen und dann est lesen oder schreiben, wenn eine exclusive Sperre erfolgreich war.

            Das Problem bei einem Counter besteht ja darin, dass Du zunächst die Datei zum Lesen öffnen musst(r), dann wieder schließen, und dann zum Schreiben öffnen(w). Mit a+ ... geht das nicht, weil Du damit die alte Zahl nicht mit der neuen überschreiben kannst. Ich habe das nur mit einem eigenen, externen Locking hinbekommen.

            btw. was hältst Du denn jetzt von meiner Methode in [pref:t=78998&m=457720] - das war definitiv kein April-Scherz ;-)

            Grüße
            Andreas

            1. Hello,

              Ein w oder w+ zerstört im Moment des Öffnesn die Datei.
              "zerstört"? in wiefern? Oder meinst Du auf '' setzen?

              Das Handle wird neu erstellt, alle alten Handles auf die Datei werden ungültig. Wenn also noch ein anderer Prozess ein Handle auf die Datei hält, und diese von dem einen Prozess mit "w" oder "w+" geöffnete wird, verleirt der andere Prozess den gültigen Zugriff auf die Datei.

              Liebe Grüße aus http://www.braunschweig.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    2. Hallo.

      Gerade eben ist wieder ein fehler aufgetreten. Hier ist erst mal der Quellcode:

      $eingabe = $name."|".$passwort."|".$level;
         $datei[$stelle] = $eingabe;
         $kette = join("\n", $datei);
         $fp = fopen("datenbank/benutzer.db","w");
         fwrite($fp,$kette);
         fclose($fp);

      $name + $passwort + $level     werden durch ein Formular übergeben
      $datei[] ist der Array in dem die Datei zeilenweise durch file() eingelesen wurde
      $stelle ist die stelle die editiert wurde und nun in dem Array ersetzt werden soll

      Wenn ich das erste Feld des Arrays editiere (also $datei[0]) wird kein Fehler angezeigt. Wenn ich jetzt jedoch ab dem zweiten Feld (also $datei[1]) schreibt er in die Datei noch eine leere Zeile vor dem eigentlich 2ten Eintrag.

      Versteht ihr was ich mein? wenn ich den 2ten eintrag editieren möchte hab ich dann im endeffekt 3 Zeilen in meiner Datei. Die erste ist richtig, die zweite ist leer und die dritte ist das editierte und korrekt ehemalig 2te Feld des Arrays.

      Wie kann ich es denn so machen dass er die Leerstelle weglässt?

      Schon mal vielen Dank im Vorraus.

      MfG
      Tarquinio

      1. Hallo Tarquinio,

        $kette = join("\n", $datei);
        [...]
        $datei[] ist der Array in dem die Datei zeilenweise durch file() eingelesen wurde
        [...]
        Wie kann ich es denn so machen dass er die Leerstelle weglässt?

        Wenn $datei[] per file() eingelesen wurde, wäre es wesentlich sinnvoller, Du würdest:

        $eingabe = $name."|".$passwort."|".$level."\n";

        sowie

        $kette = join("", $datei);

        verwenden. Denn file() lässt die Zeilenende-Zeichen am Ende der Zeile noch stehen.

        Viele Grüße,
        Christian

        1. Hello,

          wenn sowieso die gesamte Datei eingelesen werden muss, wäre es sinnvoller, gleich ein Mehrdiminensionales Array zu speichern und wieder einzulesen. Dann kann man sich den ganzen Quark mit explode() oder join() ersparen, sondern benötigt nur noch serialize() und unserialize() und das geht bis ca. 1MB verdammt schnell.

          Liebe Grüße aus http://www.braunschweig.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          1. Hi!

            wenn sowieso die gesamte Datei eingelesen werden muss, wäre es sinnvoller, gleich ein Mehrdiminensionales Array zu speichern und wieder einzulesen. Dann kann man sich den ganzen Quark mit explode() oder join() ersparen, sondern benötigt nur noch serialize() und unserialize() und das geht bis ca. 1MB verdammt schnell.

            Ach was ;-)

            Meine Lieblings-Version:

            <?php
            $array = array(1,2,3);
            $fp = fopen('cache','w');
            fputs = ($fp, "<?php\n$cache_array=".var_export($array, TRUE).";\n?>");
            fclose($fp);

            /* und im Alltag brauchen wir dann nur: */
            include('cache');
            print_r($cache_array);
            ?>

            Das ganze dann schön per opcode-cache als opcode im SHM halten, und gut is ;-)

            Ich geb zu - nicht sonderlich schön, aber es funktioniert gut :)

            Grüße
            Andreas

            1. Hello,

              Meine Lieblings-Version:

              <?php
              $array = array(1,2,3);
              $fp = fopen('cache','w');
              fputs = ($fp, "<?php\n$cache_array=".var_export($array, TRUE).";\n?>");
              fclose($fp);

              /* und im Alltag brauchen wir dann nur: */
              include('cache');
              print_r($cache_array);
              ?>

              Jetzt habe ich aber doch erstmal einen Schreck bekommen, dass ich etwas sehr brauchbares noch nicht kennen würde, aber das war eine "1.April-Lösung" von die (oder?), da sie "von hinten durch die Brust ins Auge" unter schwerer Missachtung flexibler Namensräume keinesfalls mehr leistet, als ein

              $_daten = Array( .....);
              $stream = serialize($_daten);

              $fh  = fopen(..,"a+");
              $lck = flock($fh, ..);
              fseek ( ***auf Anfang ***)
              fwrite($fh, $stream):
              ftruncate( *** auf die Länge von $stream ***);
              fclose($fh);

              Und das Lesen dann komplementär...

              Liebe Grüße aus http://www.braunschweig.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              1. Hi!

                <?php
                $array = array(1,2,3);
                $fp = fopen('cache','w');
                fputs = ($fp, "<?php\n$cache_array=".var_export($array, TRUE).";\n?>");
                fclose($fp);

                /* und im Alltag brauchen wir dann nur: */
                include('cache');
                print_r($cache_array);
                ?>

                Jetzt habe ich aber doch erstmal einen Schreck bekommen, dass ich etwas sehr brauchbares noch nicht kennen würde, aber das war eine "1.April-Lösung" von die (oder?),

                Nein, das meine ich schon ernst!

                da sie "von hinten durch die Brust ins Auge"

                naja, findest Du das jetzt ernsthaft kompliziert? Es ist nur nicht schön :)

                unter schwerer Missachtung flexibler Namensräume

                was sich aber auch recht problemlos lösen lässt, z.B. über ein singleton-pattern in einer Funktion oder Methode...

                keinesfalls mehr leistet, als ein
                [...]

                mir fällt kein effektiverer Weg ein. Vergiss das Schreiben, das wichtige ist das Lesen(zumindest wenn sich die Daten verhältnismäßig selten ändern).

                Beim Schreiben legt der Code eine Datei an, in der steht nur:

                <?php
                $cache_array = array(1,2,3);
                ?>

                Und solange sich ab diesem Zeitpunkt nichts an diesen Daten ändert, kannst Du auf die Daten zugreifen, indem Du das Script per include('datei') einbindest, da es die Daten als fertigen PHP-Code enthält, kannst Du _direkt_ darauf zugreifen.

                Und das was mir an der Idee am besten gefällt, wenn Du einen Opcode-Cache wie Turck, APC oder sonstwas einsetzt, dann wird PHP diesen erzeugten Array in Form von Opcode im Shared-memory, also im RAM halten. Das heißt, das erzeugte Script muss ab da weder von der Platte gelesen werden, noch geparst werden, es wird der Opcode aus dem Ram gelesen und ausgeführt. Und das finde ich durchaus effizient (für PHP-Verhältnisse) ;-)

                Naja, und zu Deinem Namensraum-Problem, Du darfst das halt nicht im globalen Scope einbinden, dann ist doch alles gut ;-)

                Nun gut, ein Anschauungs-Objekt:

                write.php:
                <?php
                function writeCache($data) {
                  $fp = fopen('cache','w');
                  fputs($fp,"<?php\n$cache_array=".var_export($data,TRUE).";\n?>");
                  fclose($fp);
                }
                $array = array(1,2,3);
                print_r ($array);
                writeCache($array);
                ?>

                read.php
                <?php
                function & getCache() {
                  static $cache;
                  if (!isset($cache)) {
                    include('cache');
                    $cache = $cache_array;
                  }
                  return $cache;
                }
                $blabla =& getCache();
                var_dump($blabla);
                var_dump($cache_array); // NULL!
                ?>

                So mal prinzipiell. Was spricht Deiner Meinung nach dagegen? Bedenke dabei meine Gedanken bzgl. Opcode-Cache... erst damit wird es wirklich interessant. Man könnte die Daten natürlich auch selber direkt ins SHM schreiben, naja... http://de3.php.net/manual/de/ref.sem.php

                Wenn Dir danach ist kannst Du Dich gerne mit Hilfe eines Benchmarks davon überzeugen ;-) (Am besten mal mit Opcode-Cache, mal ohne...jaja, ich weiß Du hast besseres zu tun ;-))

                Grüße
                Andreas

        2. Ihr seid wirklich gut, danke

  2. Hello,

    Ich hab ein Problem und keine Lösung gefunden.

    Dann hast Du hier im Archiv noch nicht gesucht

    http://selfsuche.teamone.de/cgi-bin/such.pl?suchausdruck=Array+Datei+Speichern&lang=on&feld=alle&index_5=on&index_6=on&hits=100
    Nur als Beispiel für eine Suche. Meine ausfühluíche Beschreibing vin Neulich ist noch nicht dabei.

    Könnt ihr mir verraten wie ich einen Array in eine datei schreiben kann? Allerdings ist in der Datei schon etwas drinne, also soll er die Datei einfach überschreiben.

    Das kann man wegschreiben, wie alle anderen Daten auch. Man muss sich immer nur Gedanken machen, ob man die Datei später als Ramdom Access oder als Textdatei benutzen will. Denn auch in einem Array könnten ja Zeilenende-Zeichen stecken.

    Ausserdem sollte er für jedes Feld des Arrays eine neue Zeile anfangen damit ich die Datei später wieder mit file() auslesen kann.

    Und warum das? Warum die Datei nicht gleich wieder in das Array einlesen?

    nützliche Funktionen:

    str_replace()
    serialize()
    unserialize()
    base64encode()
    base64decode()

    fopen()
    flock()
    fseek()
    fwrite()
    ftruncate()
    fclose()

    Liebe Grüße aus http://www.braunschweig.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen