cr: zeilenweise bearbeiten einer textdatei

hallo liebes forum,

ich möchte gerne eine txt datei zeilenweise bearbeiten. ein script in php habe ich mir bereits gebastelt, leider mit einem kleinen problem. das script liest die datei mit file() in ein array ein, dann öffnet es die datei mit fopen() und bearbeitet diese dann. wenn nun jemand dazwischenfunkt, kann es sein, dass der dazwischenfunker überschrieben wird oder etwas anderes passiert. wie bekomm ich mit fopen() den inhalt in ein gleiches array wie mit file()? das wäre doch ein weg der lösung des problems, oder sehe ich das falsch?

hier mal der erste entwurf des scripts:

<form action="" method="post">
<input type="text" name="user"><br>
<input type="text" name="wert"><br>
<input type="submit">
</form>

<?php
if(isset($_POST[user]))
{

$datei = "test.txt";
$ersetzen = $_POST[wert];
$user = $_POST[user];

$datei_inhalt = file($datei);
$datei_handle = fopen("test.txt", 'w');
foreach($datei_inhalt as $inhaltzeile)
{

$inhaltzeile = explode("|", $inhaltzeile);
if($inhaltzeile[0] == $user)
{
$inhaltzeile[1] = $ersetzen;
}
$inhaltzeile = implode("|", $inhaltzeile);

fwrite($datei_handle, $inhaltzeile);
}
fclose($datei_handle);

}

?>

Inhalt der test.txt:

user1|hinweis des users|
user2|hinweis des users2|

usw

danke für eure hilfe.

cr

  1. Hallo

    ich möchte gerne eine txt datei zeilenweise bearbeiten. ein script in php habe ich mir bereits gebastelt, leider mit einem kleinen problem. das script liest die datei mit file() in ein array ein, dann öffnet es die datei mit fopen() und bearbeitet diese dann. wenn nun jemand dazwischenfunkt, kann es sein, dass der dazwischenfunker überschrieben wird oder etwas anderes passiert. wie bekomm ich mit fopen() den inhalt in ein gleiches array wie mit file()? das wäre doch ein weg der lösung des problems, oder sehe ich das falsch?

    da sollte Dir der neue Artikel Sperren von Dateien von Christian Seiler weiterhelfen.

    Die Diskussion zu diesem Artikel ist auch noch in der Forumshauptdatei.

    fopen() bringt Dich weiter. Dort wird auf fgets() verwiesen.

    Freundliche Grüße

    Vinzenz

    1. Hallo,

      das heißt dann soviel wie:

      ich muss die datei mit fopen "r" öffnen
      sperren
      auf inhalt von der datei in ein array packen
      den inhalt der datei löschen
      das array wie gewünscht abändern
      und in die datei schreiben
      die datei schließen und freigeben?

      ist das der richtige weg? wenn ja, mit welchem befehl bekomme ich den inhalt in ein array?

      danke für deine hilfe!

      1. Hello,

        ich muss die datei mit fopen "r" öffnen
        sperren
        auf inhalt von der datei in ein array packen
        den inhalt der datei löschen
        das array wie gewünscht abändern
        und in die datei schreiben
        die datei schließen und freigeben?

        Nein, das geht nicht.
        Und leider bringt Dich der Artikel von Christian Seiler da uch nicht wirklich weiter.
        Ich will es daher mal versuchen, ganz einfach zu erklären, auch wenn mich Christian jetzt in der Luft zerreißt.

        Du hast eine Datei auf Deinem Server, die Du verändern willst

        Dazu musst Du die Datei erst einmal zu deinem Client transportieren
        Ein anderer User könnte ungefähr zur gleichen Zeit auf dieselbe Idee gekommen sein.

        das bedeutet, dass jetzt auf zwei Clients die Datei vom Zustand  gemeinsam(1) angezeigt wird.

        Du änderst die Datei, und schreibst sie zurück. Nun hat die Datei den Zustand A(2)

        Der Andere User tut einen Moment später das Gleiche. Nun hat die Datei den Zustand A(3)

        Die Problematik hast Du bereits erkannt und deshalb gefragt.

        Mit den Methoden, die Christian Seiler beschreiben hat, kommst Du nicht zum Ziel. Dies insbesondere deshalb, weil er touch() benutzt. Das ist hier für eine einfache Lösung aber schädlich.

        Wir lösen also erstmal das Problem auf einfache Weise. Diskussion ist dann noch erforderlich.

        Du benötigst ein Kriterium, dass gutwillige, aber ja "blinde" Benutzer der Scripte warnt, falls eine Konkurrenzsitzuation aufgetreten ist. Das Betriebssystem, sofern es neuer ist, liefert Dir diese Information. Es ist der Zeitpunkt der letzten Veränderung.

        Diesen Zeitpunkt musst Du nur mit der Datei zusammen auslesen und wenn Du sie zurückschreiben LÄSST, voher überprüfen LASSEN.

        Wir gehen also erstmal davon aus, dass die Datei bereits vorhanden ist.

        Datei mit fopen öffnen zum Lesen
        Datei mit flock sperren im shared Mode.
           Der reicht hier aus, weil Du nur verhindern willst, dass während Du liest
           jemand anders gerade schreibt.
        Datei lesen mit fread in eine variable
        Datei-mtime besorgen mit filemtime() http://de2.php.net/manual/de/function.filemtime.php
        Datei schließen (dadurch wird sie automatisch auch zum richtigen Zeitpunkt freigegeben)

        Die Variable für den Dateiinhalt un einer textarea ausgeben lassen

        <textarea ...><?php echo htmlspechialchars($dateiinhalt); ?></textarea>

        die Mtime, die Du beschafft hast, in einem hidden-Field des Formulares mit ausgeben

        Das Formular am Client bearbeiten

        Das Formular (an sich selbst = Affenformular) zurücksenden
        Wenn der "Speichern-Button" gedrückt war

        if (isset($_POST['btn']['save']))       ### oder so ähnlich

        Datei mit fopen öffnen
        Datei mit flock EXCLUSIV sperren
        filemtime besorgen
          Vergleichen, ob die Filemtime aus dem Hidden Field vom Client
          identisch ist mit der gerade neu besorgten

        Wenn ja

        Daten aus dem Post der textarea mit fwrite in die Datei schreiben
          Datei mit ftruncate() abschneiden (das macht man immer erst _nach_ dem Schreiben,
             damit nicht bei einem Fehler beim Schreiben alles weg ist)

        Wenn nein

        Fehlermeldung an den Client
          "Die Datei wurde zwischenzeitlich von einem anderen user verändert)

        (Kompelexere Vorgehensweise später)
             Daten mit fread in eine Variable auslesen
             Daten z.B in einer zweiten textarea wieder ausgeben an den Client
             Die aus der ersten Textarea geben wir auch in der ersten wieder aus.
             Selbes Formular, oder aber pro Textarea eins aber dann auch in jedem
               die hidden-Var mit der aktuelle Mtime einfügen
             Wir geben auch die aktuelle MTime wieder mit aus
             Zweiten Save-Button nit ausgeben, jede Textarea hat jetzt ihren eigenen
             Und das Spiel mit dem Speichern von vorne

        Datei schließen

        Probleme können darin liegen, dass die mTime zu grob ist (Sekunden-Raster).

        Wie Du Zeiklen daraus machen könntest

        $var = fread()
           $_zeilen = explode(CRLF, $var)

        PS: wenn einer fragt, woher der Name vom "Academic Locking" kommt. Das ist Slang und kommt von der Viertelstunde Unterschied. Man speichert erst CT

        Harzliche Grüße vom Berg
        http://bergpost.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

        1. Hello,

          Du änderst die Datei, und schreibst sie zurück. Nun hat die Datei den Zustand A(2)

          Der Andere User tut einen Moment später das Gleiche. Nun hat die Datei den Zustand B(2)

          solte das heißen, wird aber wohl trotzdem verstanden worden sein.

          Harzliche Grüße vom Berg
          http://bergpost.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

        2. Hallo Tom,

          Ich drei große Probleme mit einem zentralen Punkt Deines Postings:

          Mit den Methoden, die Christian Seiler beschreiben hat, kommst Du nicht zum Ziel. Dies insbesondere deshalb, weil er touch() benutzt. Das ist hier für eine einfache Lösung aber schädlich.

          a) touch() könnte man in diesem Fall auch weglassen, da man HIER beim Schreiben in jedem (!) Fall davon ausgeht, dass die Datei bereits existiert (und das ist auch jedem klar, der den Artikel gelesen und verstanden hat). Für meine Lösung (s.u.) wäre touch() aber auch nicht schädlich.

          b) Deine Pauschalisierung "kommt man nicht zum Ziel" - natürlich kommt man damit nicht ALLEINE zum Ziel, aber File Locking an sich braucht man weiterhin, Dein Posting dagegen liest sich so, als ob mein Artikel hier völlig fehl am Platze ist.

          c) Das Dateimodifikationsdatum ist in meinen Augen ein sehr schlechtes Kriterium, weil es nur eine informative Angabe ist, die das Betriebsystem liefert, man sich auf sie jedoch bei kritischen Dingen NICHT darauf verlassen sollte und - wie Du selbst bemerktest - nur sekundengenau ist.
          Eine viel sinnvollere Methode ist, mit Checksummen des Inhalts der Datei zu arbeiten (wenn sie sowieso komplett ausgelesen wird - warum nicht?).

          Folgendes Vorgehen wäre für diesen Fall am sinnvollsten (nochmal alles zusammengefasst, halt mit Prüfsummen statt Modifikationsdatum):

          1. Beim Anzeigen des Formulars wird die gesamte Datei eingelesen, dabei auch Locking betrieben, um parallelen Schreibzugriffen einen Riegel vorzuschieben (GANZ WICHTIG: Fehlerbehandlung ist hier noch nachzutragen! Der Code hier unten geht der Einfachheit wegen davon aus, dass die Funktionen immer erfolgreich sind!):

          $datei = 'datei.txt'; // oder sonstwoher  
          $fd = fopen ($datei, 'rb');  
          flock ($fp, LOCK_SH);  
          $inhalt = fread ($fp, filesize ($datei));  
          fclose ($fp);
          

          1a. Danach wird eine Prüfsumme des Inhalts berechnet. Nachdem es hier nicht um kryptographische Sicherheit geht, sondern nur um Konsistenzprüfung, dürfte MD5 vollkommen ausreichend sein:

          $pruefsumme = md5 ($inhalt);

          1b. Nun wird der Inhalt zeilenweise aufgespalten:

          $zeilen = preg_split ("/\r\n|\n|\r/", $inhalt);

          Danach enthält $zeilen ein Array mit allen Zeilen der Datei - allerdings OHNE die Zeilentrennzeichen - das ist der Unterschied zu file().

          1c. Nun wird das Formular erzeugt, dort gibt es zum einen die Felder, die sich an Hand von $zeilen ergeben (wie Du's halt bisher erzeugst). ZUSÄTZLICH gibt es ein Hidden-Feld <input type="hidden" name="pruefsumme" value="...">, wobei das '...' durch den Inhalt der Variable $pruefsumme zu ersetzen ist.

          2. Wenn das Formular ankommt, wird es zuerst validiert, damit die Benutzeringaben gültig sind. Wenn nicht, bekommt es der User wieder vorgesetzt. Ist dies geschehen, wird die Datei wieder geöffnet (diesmal zum Lesen & Schreiben), die Prüfsumme erneut generiert und dann der Dateizeiger zurückgesetzt (wir gehen davon aus, dass die Datei in der Zwischenzeit NICHT gelöscht wurde, auch hier wieder: FEHLERBEHANDLUNG SELBST NACHTRAGEN!):

          $datei = 'datei.txt'; // oder sonstwoher  
          $fd = fopen ($datei, 'rb+'); // zum lesen UND schreiben  
          flock ($fp, LOCK_EX); // EXKLUSIVE sperre  
          $inhalt = fread ($fp, filesize ($datei));  
          $pruefsumme = md5 ($inhalt);  
          fseek ($fp, 0, SEEK_SET);  
          // DATEI NICHT SCHLIESSEN!
          

          Nun wird $pruefsumme mit der über das Formular übermittelten Prüfsumme verglichen ($pruefsumme == $_POST['pruefsumme']). Wenn sie übereinstimmen, wurde die Datei NICHT verändert seit dem Anzeigen des Formulars, dann kann der Inhalt problemlos zurückgeschrieben werden. Dies geschieht, indem die Datei "zurechtgestutzt" wird und danach ganz Normal fwrite() genutzt wird:

          if ($pruefsumme == $_POST['pruefsumme']) {  
            ftruncate ($fp, 0);  
            fwrite ($fp, $neuerInhalt);  
            fclose ($fp);  
          } else {  
            fclose ($fp);  
            // siehe unten...  
          }
          

          Wie Du an $neuerInhalt kommst, bleibt Dir (= dem mit dem Problem) überlassen. Du kannst an dieser Stelle zum Beispiel den alten Inhalt wieder zeilenweise aufteilen und die POST-Daten an die entsprechenden Zeilen einfügen und dann per join ("\n", $zeilen) die Zeilen wieder zu einem String zusammenfügen oder Du kannst nur aus den POST-Daten den neuen Inhalt erstellen - das bleibt ganz Dir überlassen. Sobald die Datei geschlossen ist, war alles erfolgreich und Du kannst Dich zurücklehnen.

          Nun zur else-Bedingung, die auftritt, wenn die Prüfsumme NICHT übereinstimmt. Dann ist folgender Fall eingetreten: Jemand hat die Datei modifiziert, NACHDEM Du das Formular an den Client ausgeliefert hast, BEVOR es jedoch zurückgekommen ist. Je nachdem wie komfortabel es für den Benutzer machen willst, kannst Du Dir überlegen, wie Du darauf reagierst. Du könntest eine Fehlermeldung ausgeben. Du könntest die Unterschiede zwischen den verschiedenen Versionen anzeigen. Und so weiter, und so fort.

          PS: wenn einer fragt, woher der Name vom "Academic Locking" kommt. Das ist Slang und kommt von der Viertelstunde Unterschied. Man speichert erst CT

          Das ist - mit Verlaub - Quatsch. "Academic Locking" ist eindeutig eine Wortschöpfung von Dir (d.h. wenn schon nennst DU es so, nicht MAN!), denn die einzigen relevanten Google-Suchtreffer sind ein paar weitere Postings in diesem Forum von Dir.

          Zudem: "Akademische Viertelstunde" ist eine rein deutsche Redewendung - im Englischen spricht man ausschließlich von 'c.t.'.

          Und schließlich ist hier "Locking" fehl am Platze, weil das, was hier gemacht wird, kein Locking ist. Hier wird zwar gesperrt beim Zugriff auf die Datei - dort aber ganz normal, dafür braucht man keinen zusätzlichen Begriff erfinden. Und die Abfrage, ob sich in der Zwischenzeit etwas an der Datei geändert hat, ist mit SICHERHEIT kein Locking, da sie ja nur dazu dient, Veränderungen zu ERKENNEN, nicht zu VERHINDERN.

          Viele Grüße,
          Christian

          1. Hello Christian,

            entschuldige bitte, wenn das jetzt so aussah, als wollte ich Deinen Artikel runtermachen.
            Der ist gut und wichtig. Das habe ich auch nicht bezweifelt.

            Der Disput ist (auch hier) nur aufgekommen, weil ich unter

            "eine Datei bearbeiten"

            verstanden habe, dass cr den Inhalt ansehen will, um ihn zu editierern, also mit einer erheblichen Zeitlücke zwischen Lesen und Schreiben.

            Wenn nur ein "update" an einem Datensatz über einen Schlüsselwert gemacht werden soll, und es nur wichtig ist, was hinterher im Datensatz drinsteht, ist das alles nicht nötig. Und dann verstehe ich Vinzenz' Einwand auch, dass man den Inhalt einer Datei zum Ändern nicht erst zum Client transportieren muss.

            Mit den Methoden, die Christian Seiler beschreiben hat, kommst Du nicht zum Ziel. Dies insbesondere deshalb, weil er touch() benutzt. Das ist hier für eine einfache Lösung aber schädlich.

            Hab ich das irgendwo so geschrieben? Kann ich jetzt nicht finden, will mich da auch nicht rausreden. Der ganze Knoten löst sich doch von selbst auf. Wir haben hier alle anneinander vorbei geredet.

            Tut mir also wirklich leid.

            Touch kann man beim zeitversetzten Lesen und Schreiben auf Dateien nicht benutzen, um eine vermeintlich nicht vorhandene Datei anzulegen, weil touch() sowohl die access-time als auch die modifiy-time ändert (ctime habe ich jetzt nicht überprüft), obwohl die Datei gar nicht verändert wird. Das hat für Touch sicher seinen Sinn, aber eben nicht für das vermutete Problem.

            Damit würde man also ein generisch an die Datei gebundenes Kriterium zerstören, dass einem für das Erkennen einer zwischenzeitlichen Änderung zur Verfügung steht. Auf nichts anderes bezog sich mein Hinweis.

            b) Deine Pauschalisierung "kommt man nicht zum Ziel" - natürlich kommt man damit nicht ALLEINE zum Ziel, aber File Locking an sich braucht man weiterhin, Dein Posting dagegen liest sich so, als ob mein Artikel hier völlig fehl am Platze ist.

            vollkommen verkehrt verstanden. Bitte nochmals um Entschuldigung.

            c) Das Dateimodifikationsdatum ist in meinen Augen ein sehr schlechtes Kriterium, weil es nur eine informative Angabe ist, die das Betriebsystem liefert, man sich auf sie jedoch bei kritischen Dingen NICHT darauf verlassen sollte und - wie Du selbst bemerktest - nur sekundengenau ist.

            Die grobe Granularitätr würde mich auch abschrecken.
            Aber wenn man sich auf das Betriebssystem nicht verlassen kann, worauf dann?

            Eine viel sinnvollere Methode ist, mit Checksummen des Inhalts der Datei zu arbeiten (wenn sie sowieso komplett ausgelesen wird - warum nicht?).

            Das ist eine gute Idee.
            Wie sicher kann man sein, dass die bei größeren Dateien mit unterschiedlichem Inhalt auch noch unterschiedlich sind?

            Folgendes Vorgehen wäre für diesen Fall am sinnvollsten (nochmal alles zusammengefasst, halt mit Prüfsummen statt Modifikationsdatum):

            1. Beim Anzeigen des Formulars wird die gesamte Datei eingelesen, dabei auch Locking betrieben, um parallelen Schreibzugriffen einen Riegel vorzuschieben (GANZ WICHTIG: Fehlerbehandlung ist hier noch nachzutragen! Der Code hier unten geht der Einfachheit wegen davon aus, dass die Funktionen immer erfolgreich sind!):

            $datei = 'datei.txt'; // oder sonstwoher

            $fd = fopen ($datei, 'rb');
            flock ($fp, LOCK_SH);

            $inhalt = fread ($fp, filesize ($datei));  ## Achtung, wenn sie leer ist ;-)

            fclose ($fp);

              
              
            
            > 1a. Danach wird eine Prüfsumme des Inhalts berechnet. Nachdem es hier nicht um kryptographische Sicherheit geht, sondern nur um Konsistenzprüfung, dürfte MD5 vollkommen ausreichend sein:  
              
              
            
            > `$pruefsumme = md5 ($inhalt);`  
            >   
            > 1b. Nun wird der Inhalt zeilenweise aufgespalten:  
            >   
            > `$zeilen = preg_split ("/\r\n|\n|\r/", $inhalt);`  
            >   
            > Danach enthält $zeilen ein Array mit allen Zeilen der Datei - allerdings OHNE die Zeilentrennzeichen - das ist der Unterschied zu file().  
              
            ...was ja für die Weiterverarbeitung auch besser ist, weil sonst immer das letzte Element des Zeilenarrays noch mit rtrim() behandelt werden muss. Die könnten bei PHP ruhig mal einen optionalen Parameter einführen, der den Zeilenumbruch bei file() automatisch entfernt. Er gehört nicht zu den Daten.  
              
            
            > 1c. Nun wird das Formular erzeugt, dort gibt es zum einen die Felder, die sich an Hand von $zeilen ergeben (wie Du's halt bisher erzeugst). ZUSÄTZLICH gibt es ein Hidden-Feld `<input type="hidden" name="pruefsumme" value="...">`, wobei das '...' durch den Inhalt der Variable $pruefsumme zu ersetzen ist.  
            >   
              
            
            > 2. Wenn das Formular ankommt, wird es zuerst validiert, damit die Benutzeringaben gültig sind. Wenn nicht, bekommt es der User wieder vorgesetzt. Ist dies geschehen, wird die Datei wieder geöffnet (diesmal zum Lesen & Schreiben), die Prüfsumme erneut generiert und dann der Dateizeiger zurückgesetzt (wir gehen davon aus, dass die Datei in der Zwischenzeit NICHT gelöscht wurde, auch hier wieder: FEHLERBEHANDLUNG SELBST NACHTRAGEN!):  
            >   
            > ~~~
            
            $datei = 'datei.txt'; // oder sonstwoher  
            
            > $fd = fopen ($datei, 'rb+'); // zum lesen UND schreiben  
            > flock ($fp, LOCK_EX); // EXKLUSIVE sperre  
            
              $inhalt = fread ($fp, filesize ($datei));   ## wieder beachten, dass Länge > 0 sein muss  
            
            > $pruefsumme = md5 ($inhalt);  
            > fseek ($fp, 0, SEEK_SET);  
            > // DATEI NICHT SCHLIESSEN!
            
            

            Nun wird $pruefsumme mit der über das Formular übermittelten Prüfsumme verglichen ($pruefsumme == $_POST['pruefsumme']). Wenn sie übereinstimmen, wurde die Datei NICHT verändert seit dem Anzeigen des Formulars, dann kann der Inhalt problemlos zurückgeschrieben werden. Dies geschieht, indem die Datei "zurechtgestutzt" wird und danach ganz Normal fwrite() genutzt wird:

            if ($pruefsumme == $_POST['pruefsumme']) {

            ftruncate ($fp, 0);
              fwrite ($fp, $neuerInhalt);
              fclose ($fp);
            } else {
              fclose ($fp);
              // siehe unten...
            }

            
            >   
            > Wie Du an $neuerInhalt kommst, bleibt Dir (= dem mit dem Problem) überlassen. Du kannst an dieser Stelle zum Beispiel den alten Inhalt wieder zeilenweise aufteilen und die POST-Daten an die entsprechenden Zeilen einfügen und dann per `join ("\n", $zeilen)` die Zeilen wieder zu einem String zusammenfügen oder Du kannst nur aus den POST-Daten den neuen Inhalt erstellen - das bleibt ganz Dir überlassen. Sobald die Datei geschlossen ist, war alles erfolgreich und Du kannst Dich zurücklehnen.  
            >   
            > Nun zur else-Bedingung, die auftritt, wenn die Prüfsumme NICHT übereinstimmt. Dann ist folgender Fall eingetreten: Jemand hat die Datei modifiziert, NACHDEM Du das Formular an den Client ausgeliefert hast, BEVOR es jedoch zurückgekommen ist. Je nachdem wie komfortabel es für den Benutzer machen willst, kannst Du Dir überlegen, wie Du darauf reagierst. Du könntest eine Fehlermeldung ausgeben. Du könntest die Unterschiede zwischen den verschiedenen Versionen anzeigen. Und so weiter, und so fort.  
              
              
              
              
              
              
              
            Harzliche Grüße vom Berg  
            <http://bergpost.annerschbarrich.de>  
              
            Tom
            
            -- 
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen  
            Nur selber lernen macht schlau  
            Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)  
              
            ![](http://bitworks.de/~selfHTML/Virencheck.gif)  
            
            
            1. Hallo,

              c) Das Dateimodifikationsdatum ist in meinen Augen ein sehr schlechtes Kriterium, weil es nur eine informative Angabe ist, die das Betriebsystem liefert, man sich auf sie jedoch bei kritischen Dingen NICHT darauf verlassen sollte und - wie Du selbst bemerktest - nur sekundengenau ist.

              Die grobe Granularitätr würde mich auch abschrecken.
              Aber wenn man sich auf das Betriebssystem nicht verlassen kann, worauf dann?

              Wie gesagt: Das Modifikationsdatum ist eine rein informative Größe. Es gibt wenige Fälle, in denen es sinnvoll ist, sich darauf zu verlassen. Um Änderungen an Dateien zu erkennen ist es jedoch in der Regel (!) ungeeignet.

              Wenn Du das Modifikationsdatum einsetzen willst, solltest Du erstmal nachweisen, dass ein geändertes Modifikationsdatum unproblematisch für den gegebenen Fall ist, ansonsten die Finger von lassen. Dies ist zum Beispiel bei »make« der Fall - wenn etwas nicht klappt, dann sieht man's ja sofort und kann ein »make clean« drüberlaufen lassen, bevor man nochmal anfängt.

              Eine viel sinnvollere Methode ist, mit Checksummen des Inhalts der Datei zu arbeiten (wenn sie sowieso komplett ausgelesen wird - warum nicht?).

              Das ist eine gute Idee.
              Wie sicher kann man sein, dass die bei größeren Dateien mit unterschiedlichem Inhalt auch noch unterschiedlich sind?

              Bei MD5? Extrem sicher. Wie gesagt: Das hier ist keine kryptographische Anwendung, hier hat ein Angreifer nichts davon, wenn die Hashes gleich wären, und die bisher einzigen Kollisionen bei MD5 wurden explizit konstruiert, die sind nicht zufällig aufgetreten. Insofern ist ein MD5-Hash eine extrem gute Möglichkeit, Änderungen an Dateien zu erkennnen, wenn man davon ausgehen kann, dass niemand ein Interesse hat, diesen Mechanismus auszutricksen (was hier der Fall ist).

              Viele Grüße,
              Christian

            2. Hi Tom,

              Die könnten bei PHP ruhig mal einen optionalen Parameter einführen, der den Zeilenumbruch bei file() automatisch entfernt. Er gehört nicht zu den Daten.

              ist doch seit PHP 5.0 (?) dabei:

                
              $line = file('filename.ext', FILE_IGNORE_NEW_LINES);  
              
              

              Scheint mir aber (wieder mal) nicht konsequent umgesetzt worden zu sein. Bei Windows-Zeilenumbrüchen gibt es wohl Probleme (nicht getestet). Also doch rtrim() nutzen...

              Gruß,
              Andreas.

              1. Hello Andreas,

                Die könnten bei PHP ruhig mal einen optionalen Parameter einführen, der den Zeilenumbruch bei file() automatisch entfernt. Er gehört nicht zu den Daten.

                ist doch seit PHP 5.0 (?) dabei:

                $line = file('filename.ext', FILE_IGNORE_NEW_LINES);

                  
                Danke! Sehr sogar!  
                  
                Daran habe ich bestimmt immer vorbeigelesen, obwohl ich ja förmlich darauf gewartet habe, dass es endlich aufgenommen wird. Aber vielleicht habe ich aus Versehen immer nur in die deutsche Doku geschaut. Ich merke das manchmal überhaupt nicht mehr, dass ich englisch lese. Wenn mein Nachbar dann mal kommt mit 'ner Frage und über die Schulter mitliest, dann mault der mich immer an "kannst Du nicht mal die deutsche Doku nehmen?" Ich stutze und denke "wieso, hab ich doch" Denkste, war die englische...  
                  
                Bis sie den Bug auch noch rausbauen, kann man ja Christians Version nehmen  
                  
                  $\_zeilen = preg\_split ("/\r\n|\n|\r/", $inhalt);  
                  
                  
                  
                Harzliche Grüße vom Berg  
                <http://bergpost.annerschbarrich.de>  
                  
                Tom
                
                -- 
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen  
                Nur selber lernen macht schlau  
                Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)  
                  
                ![](http://bitworks.de/~selfHTML/Virencheck.gif)  
                
                
      2. Hallo

        ist das der richtige weg? wenn ja, mit welchem befehl bekomme ich den inhalt in ein array?

        das habe ich Dir doch schon verlinkt: mit fgets.
        Statt in einen Puffer schreibst Du in Arrayelemente.
        Die maximale Zeilenlänge solltest Du natürlich auch berücksichtigen :-)

        Dass nach dem Wegschreiben jemand anderes diese Datei mit ganz anderen Inhalten
        überschreibt, kannst Du nicht verhindern.

        Freundliche Grüße

        Vinzenz

        1. Hello,

          Dass nach dem Wegschreiben jemand anderes diese Datei mit ganz anderen Inhalten
          überschreibt, kannst Du nicht verhindern.

          ?

          Du meinst aber sicher, nachdem er sie vorher nochmals ausgelesen, zum Client transporiert, dort durchgearbeitet und dann nach einer viertel Stunde wegschreiben lassen hat?

          Schau Dir mal mein Beispiel unter http://selfhtml.bitworks.de/artikel_locking/adressen.php an.
          Lade es in zwei Fenstern.
          Blättere durch und ändere einen Datensatz.

          Hier wird allerdings noch nicht auf Satzebene geprüft, sondern nur auf Dateiebene, aber es funktioniert ungefähr so, wie ich es in https://forum.selfhtml.org/?t=161446&m=1050300 beschrieben habe.

          Harzliche Grüße vom Berg
          http://bergpost.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

          1. Hallo Tom,

            Dass nach dem Wegschreiben jemand anderes diese Datei mit ganz anderen Inhalten
            überschreibt, kannst Du nicht verhindern.

            ?

            Du kannst nicht verhindern, dass irgend jemand anderes, der auf irgeneinem
            beliebigen Weg schreibenden Zugriff auf diese Datei hat, diese mit anderen
            Inhalten überschreibt. Nichts mehr und nichts weniger.

            Man braucht eine Datei nicht zu lesen, um sie überschreiben zu können.
            Man muss sie auch nicht zu einem Client transportieren. Alle Aktionen können
            auf dem Server ablaufen.

            Freundliche Grüße

            Vinzenz

            1. *wuff*

              Hello,

              Du kannst nicht verhindern, dass irgend jemand anderes, der auf irgeneinem
              beliebigen Weg schreibenden Zugriff auf diese Datei hat, diese mit anderen
              Inhalten überschreibt. Nichts mehr und nichts weniger.

              Das hast Du aber nicht gesagt und es gehörte ohne ausfühlichen Zusatz auch nicht zum Thema!

              Man braucht eine Datei nicht zu lesen, um sie überschreiben zu können.
              Man muss sie auch nicht zu einem Client transportieren. Alle Aktionen können
              auf dem Server ablaufen.

              Was hat das denn mit der Frage von cr zu tun?

              Was soll denn das jetzt?

              cr hatte nach einem geordneten Zugriff auf die Daten in einer Multi-User-Umgebung mit PHP gefragt und nicht danach, was geschehen kann, wenn Laien am Server gespielt haben.

              Wenn ich nicht will, dass mir auf dem Fileserver irgendwelche User meine Daten kaputt machen, gebe ich  ihnen gar keinen Zugriff darauf, und zwar auf Filesystem-Ebene. Dafür ist ein Fileserver nämlich da.

              Wie regelst Du denn Bei MySQL solche konkurrierenden Zugriffe im Client-Server-Umfeld?

              Harzliche Grüße vom Berg
              http://bergpost.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau
              Ein Jammer ist auch, dass die Dummen so selbstsicher und die Klugen voller Zweifel sind. Das sollte uns häufiger zweifeln lassen :-)

              1. Hallo Tom und anne anderen,

                erstmal danke für die vielen Antworten!

                ich werde mich die Tage mal mit Hilfe der Aussagen an dem Scirpt probieren.

                Nebenbei habe ich in meinem eigenen Archiv gesucht und das hier gefunden...was hgaltet ihr davon?

                if(isset($_POST['name']) && isset($_POST['email']))
                {
                 $neuername = $_POST['name'];
                 $neuername = htmlspecialchars($neuername);
                 $neuername = str_replace("\r\n","",$neuername);
                 $neuername = str_replace("|","",$neuername);
                 $neueemail = $_POST['email'];
                 if($neuername != "")
                 {
                  $legitimation = fopen("files/legitimation.txt", "rb+");
                  $legitimation_lock = flock($legitimation, LOCK_EX);
                  $legitimation_daten = fread($legitimation, filesize('files/legitimation.txt'));
                  $legitimation_daten = explode("\n", $legitimation_daten);
                  foreach($legitimation_daten as $key => $legitimation_daten_zeile)
                  {
                   $legitimation_daten[$key] = explode("|", $legitimation_daten_zeile);
                   if($legitimation_daten[$key][3] == $id)
                   {
                    $legitimation_daten[$key][6] = $neuername;
                   }
                  }
                  foreach($legitimation_daten as $key => $legitimation_daten_zeile)
                  {
                   $legitimation_daten[$key] = implode("|", $legitimation_daten_zeile);
                  }
                  $legitimation_daten = implode("\n", $legitimation_daten);
                  fseek($legitimation, 0, SEEK_SET);
                  fwrite($legitimation, $legitimation_daten);
                  ftruncate($legitimation, strlen($legitimation_daten));
                  fclose($legitimation);
                  $erfolg = 1;
                 }
                 else
                 {
                  $erfolg = 2;
                 }
                }

                liebe grüße

                1. Hallo,

                  Nebenbei habe ich in meinem eigenen Archiv gesucht und das hier gefunden...was hgaltet ihr davon?

                  Das Datei-Locking wird korrekt durchgeführt. Allerdings wird hier - im Gegensatz zu dem, was hier im Thread diskutiert wurde, nicht überprüft, ob sich der Dateiinhalt seitdem geändert hat. Daher: Du kannst Dir mit der Funktion sicher sein, dass die Datei nicht korrupt wird, Datenverlust kannst Du aber nicht ausschließen. Allerdings ließe sich in den bestehenden Code diese Überprüfung mit vergleichsweise wenig Aufwand einbauen.

                  Ferner zwei Anmerkungen:

                  $legitimation_daten = explode("\n", $legitimation_daten);

                  Nunja, ein preg_split ("/\r\n|\n|\r/", ... wäre in meinen Augen hier besser, damit man sich nicht auf die Zeilenende-Zeichen verlässt. Zwar wird in der Funktion weiter unten mit implode immer "\n" als Trenner verwendet (das ist gut so!), allerdings sollte man als Programmierer immer großzügig in dem sein, was man akzeptiert und strikt in dem sein, was man ausgibt. Sprich: implode mit "\n" lassen, aber lieber großzügiger beim Aufspalten sein. Dann macht man sich auch keine Probleme, sollte man z.B. unter Windows die Datei mal von Hand bearbeiten.

                  fseek($legitimation, 0, SEEK_SET);
                    fwrite($legitimation, $legitimation_daten);
                    ftruncate($legitimation, strlen($legitimation_daten));

                  Diese Art, mit fseek, fwrite und ftruncate umzugehen, ist etwas "um-die-Ecke-gedachter" als die anderen Vorschläge hier (einschließlich meinem), allerdings vermutlich auch einen Tick effizienter - es wird der Speicherplatz der bisherigen Datei wiederverwendet (was natürlich auch im anderen Fall passieren _kann_, falls der Kernel von sich aus optimiert, bei Deiner Lösung aber zwangsläufig passiert).

                  Viele Grüße,
                  Christian

                  1. Hallo Christian,

                    wenn ich nun das von mir eingestellte script wie folgt verwende sollte es doch keine probleme geben?:

                    die txt enthält z.b. folgende inhalte...

                    stefan|info@stefan.de|Hamburg|
                    tom|tom@gmx.de|Wolfsburg|
                    max|mm@web.de|Berlin|

                    usw...

                    wenn ich nun ein formular habe, das daten des users tom ädnern möchte,
                    ist dies doch egal, ob sich zwischenzeitlich der inhalkt ändert?
                    ich suche nach tom, wenn tom gefunden änder ich die e-mail adresse in die neue ab. ob da nun 3 leute in der txt stehen oder 300 ist doch egal? solange zwischen dem lesen des inhalts, bearbeiten und abspeichern des neuen inhalts niemand dazwischenfunkt?

                    oder sehe ich das falsch?

                    danke und grüße

                    1. Hallo,

                      ich suche nach tom, wenn tom gefunden änder ich die e-mail adresse in die neue ab. ob da nun 3 leute in der txt stehen oder 300 ist doch egal? solange zwischen dem lesen des inhalts, bearbeiten und abspeichern des neuen inhalts niemand dazwischenfunkt?

                      Wenn Du *NUR* »tom« änderst und es Dir egal ist, ob sich der Eintrag »tom« in der Zwischenzeit (zwischen Formularanzeige und Abschicken) geändert hat: ja.

                      Viele Grüße,
                      Christian

                      1. ok,

                        danke für deine hilfe und natürlich auch von der hilfe allen anderen!

                        selfhtml ist wohl eines der besten info-portal für websprachen.

                        grüße cr