Pedda: Datei lesen und erweitern

Hallo zusammen,

ich hab' da ein "klitzekleines" Problem, bei dem ihr meine letzte Hoffnung seid *g*. Meine Suche nach passenden Antworten war nämlich bisher leider vergebens :(
So sieht's aus:
Ich habe eine Datei daten.dat, in der viele, viele Zeilen stehen.
Aufbau einer Zeile:
01.01.2001|name@host.de|daten1|daten2|daten3

Das zeilenweise Auslesen der Datei ist nicht das Problem - das funzt vorherragend.
Das Problem das ich habe ist eher die Erweiterung der Datei.
Und zwar soll ein neuer Datensatz (also eine neue Zeile) am ANFANG der Datei eingefügt werden.
Mit fopen($filename, "r+") setze ich den Zeiger zwar auf den Anfang der Datei, doch wird mir dann der erste bereits bestehende Datensatz dabei immer durch den neuen überschrieben :(

Kann mir da bitte jemand weiterhelfen ?

Thnx und Gruss aus Münster

Pedda

  1. Holladiewaldfee,

    Mit fopen($filename, "r+") setze ich den Zeiger zwar auf den Anfang der Datei, doch wird mir dann der erste bereits bestehende Datensatz dabei immer durch den neuen überschrieben :(

    Soweit ich weiß geht das nicht.
    Du kannst höchstens die gesamte Datei auslesen, den Zeiger wieder an den Anfang setzen, dann den neuen Datensatz reinschreiben und den zuvor ausgelesenen Rest hinterherschieben.

    Ciao,

    Harry

    --
      Schnee :) Skitour gefällig?
      http://harry.ilo.de/projekte/berge/
    1. Hi,

      ...hmpf.... aber sowas um den Dreh hab ich mir schon gedact :(
      Naja... dann halt über diesen Umweg *g*

      Thnx und Gruss aus Münster

      Pedda

  2. Hallo Pedda,

    Hallo zusammen,

    Das zeilenweise Auslesen der Datei ist nicht das Problem - das funzt vorherragend.
    Das Problem das ich habe ist eher die Erweiterung der Datei.
    Und zwar soll ein neuer Datensatz (also eine neue Zeile) am ANFANG der Datei eingefügt werden.

    Mir fallen spontan zwei Möglichkeiten ein:

    1. Erstelle eine neue Datei. Füge den neuen Datensatz ein. Hänge die alte Datei hinten an. Lösche die alte Datei. Benenne die neue Datei um, so dass sie den Namen der alten Datei erhält.

    2. Lese die komplette Datei in ein Array ein (benötigt bei vielen Datensätzen viel Speicher). Schliesse die Datei. Öffne die Datei zum Schreiben. Schreibe zuerst den neuen Datensatz weg. Schreibe anschliessend das Array weg.

    3. Empfehlenswerter ist dagegen das Verwenden einer Datenbank :-)

    Thnx und Gruss aus Münster

    Pedda

    Freundliche Grüße,

    Vinzenz

    1. Hallo,

      1. Erstelle eine neue Datei. Füge den neuen Datensatz ein. Hänge die alte Datei hinten an. Lösche die alte Datei. Benenne die neue Datei um, so dass sie den Namen der alten Datei erhält.

      IMHO zuviele Datei-Aktionen.
      Aber natuerlich eine brauchbare Moeglichkeit.
      Die auch von der dclp-FAQ empfohlen wird:
      http://www.dclp-faq.de/q/q-datei-einfuegen.html

      1. Lese die komplette Datei in ein Array ein (benötigt bei vielen Datensätzen viel Speicher).

      Warum nicht gleich in einen String?
      file_get_contents() ist IMHO dafuer praedestiniert.

      Damit hat man nur zwei Datei-Aktionen:

      // Definieren der neuen Zeile und des Dateinamens:
      $neuezeile="01.01.2001|name@host.de|daten1|daten2|daten3\n";
      $dateiname="daten.dat";

      // 1. Einlesen des bisherigen Inhalts in einen String:
      $alterinhalt=file_get_contents($dateiname);

      // 2. Schreiben der neuen Zeile und des bisherigen Inhalts in die Datei.
      $handle=fopen($dateiname, "w");
      fwrite($handle, $neuezeile.$alterinhalt));
      fclose($handle);

      Natuerlich muss man das ganze noch mit einer anstaendigen
      Fehlerbehandlung "einpacken", siehe auch:
      http://www.php.net/manual/de/function.fopen.php
      http://www.php.net/manual/de/function.fwrite.php
      http://www.php.net/manual/de/function.file-get-contents.php

      1. Empfehlenswerter ist dagegen das Verwenden einer Datenbank :-)

      Es ist vielleicht bequemer.
      Ob es empfehlenswerter, zweckmaessiger, schneller, ... ist,
      kann man IMHO nur sagen, wenn man mehr Details kennt,
      z.B. Anzahl der Datensaetze, Haeufigkeit der Mutationen,
      Zweck der ganzen Sache... ;-)

      mfg, Thomas

      1. Hi Thomas,

        das ist super, danke auch von meiner Seite! Gestatte mir die klitzekleine Korrektur:

        fwrite($handle, $neuezeile.$alterinhalt));

        Doppelte Klammer führt zum Fehler, also:

        fwrite($handle, $neuezeile.$alterinhalt);

        Ansonsten fantastisch! :)

      2. Hello,

        IMHO zuviele Datei-Aktionen.

        Nein, es sind nicht zuviele Dateiaktionen, wenn man sie auf OS-Ebene ausführen lässt, also mit system(). Das Anhängen der alten Daten an die neuen geht selbst bei großen Dateien (8MB und mehr) innerhabl Sekundenbruchteilen.

        Aber natuerlich eine brauchbare Moeglichkeit.

        Es ist die einzig praktikable!

        Die auch von der dclp-FAQ empfohlen wird:
        http://www.dclp-faq.de/q/q-datei-einfuegen.html

        1. Lese die komplette Datei in ein Array ein (benötigt bei vielen Datensätzen viel Speicher).

        Warum nicht gleich in einen String?
        file_get_contents() ist IMHO dafuer praedestiniert.

        file_get_contents() ist für Konkurrierenden Betrieb meistens ungeeignet. Denn denk an ein vernünftiges Locking. Das geht mit file_get_contents() nur durch die Hintertür, da man an das Handle nicht herankommt.

        Man sollte also so vorgehen, wie von Vinzenz beschrieben und sich ein genaues Zeit-Zustands-Diagramm für die Daten machen. Alle Applikationen, die dann auf diese Dateien zugreifen, müssen sich an dieselbe Vorgehensweise halten, am besten, dasselbe Zugriffsmodul einbinden (Class oder include).

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

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
  3. Hi Pedda,

    ein sehr ähnliches Problem hatte ich unlängst auch mal und hab dafür eine wohl etwas unelegantes, aber funktionierendes Script geschrieben:

    <?php

    // Zeichen für den Zeilenumbruch
    define("N",chr(13).chr(10));

    // Datei einlesen
    $datei = "Datei.txt";

    // Jede Zeile wird ein Array-Element
    $DateiArray = file($datei);

    // neuer Satz
    $neuerSatz = "bla*bla*bla*bla#bla§";

    // wird vorne zugefügt
    array_unshift($DateiArray,$neuerSatz);

    // Länge des neuen Arrays wird ermittelt
    $ende = sizeof($DateiArray);

    // String wird erzeugt, der letztlich geschrieben wird
    $ausgabe = "";

    $count = 0;
    while ($count < $ende)
      {

    // explode isoliert den maßgeblichen Satz ohne den Zeilenumbruch
      $ray = explode("§", $DateiArray[$count]);

    // String wird erzeugt
      $ausgabe = $ausgabe . $ray[0] . "§" . N;
      $count++;
      }

    // Datei wird geschrieben
    $fx = fopen ("Datei.txt","w");
    fwrite($fx,$ausgabe);

    ?>

    Das funktioniert, sieht aber irgendwie krüppelig aus. :)

  4. Idee:

    schreibe den neuen Satz doch hintendran.

    Beim Auslesen der Datei dann auf den letzten Satz aufsetzen und rückwärts lesen. Womöglich kann dann ein parallel arbeitendes Programm sogar gleichzeitig einen weiteren Satz anhängen.

    Kalle