nokill: Löschen einer Zeile aus Datei

Hi,

mein Problem ist folgendes: Ich schriebe der zeit an einem Clanwarscript in Php soweit so gut. Die Routine zum schreiben der Clanwars in eine Datei habe ich hinbekommen jetzt möcht ich, dass der Benutzer auch wieder Clanwars löschen kann soweit so gut. Mein Problem ist jetzt das ich es nicht hinbekommen, dass die Clanwars wieder richtig in die Datei reingeschreiben werden, aber ich zeige euch einfach mal den Quelltext:

clanwar_edit.php:

<? [...]

$datei = "clanwars.dat";               $cwid  = $_GET['cwid'];

switch($_GET['action'])                    {                         //Auswahl des Clanwar, der geloescht werden soll                         default:                         $Siteselect = "-= Delete clanwar =-                                        <br />                                        <br />                                        <form action="$PHP_SELF" method="get">                                             <div>                                             Clanwarid:<input type="text" name="cwid">                                                       <input type="hidden" name="action" value="get">                                             </div>                                             <div>                                                   <input type="submit" name="go" value="Go">                                                   <input type="reset" name="Reset" value="Reset">                                             </div>                                        </form>                                       ";                              break;                         case "get":                         if(file_exists($datei))                              {                                   $inh = file($datei,"r");                                   $anzahl = count($inh);                                   for($i = 0, $var = 1, $anzzeilen = 1; $i < $anzahl; $i++)                                        {                                             $eintrag     = explode("\n",$inh[$i]);                                             trim($eintrag['0']);                                             $zeile[$var] = $eintrag['0']; //lese jede Zeile in ein Array aus

$var++;                                             //alle zeilen zaehlen                                             $anzzeilen++;

echo "$anzzeilen<br>";                                        }

if ($cwid<=$anzzeilen)//hier prüfe ich ob die Zeile, in der der clanwar stehen soll existieren                                        {                                             unset($zeile[$cwid]);                                             trim($zeile);

$newfp      = fopen($datei,"w");                                             $newcontent = implode("",$zeile); // hier liest er das array in eine var aus und hier ist wohl auch der Fehler!!!!!                                             fputs($newfp,$newcontent);                                             fputs($newfp,"\n");                                             fclose($newfp);

$Siteselect = "v0.3 beta1                                                            <br />                                                            <br />                                                            <div class="success">                                                                 Clanwar deleted successfully!                                                            </div>                                                           ";                                        }                                   else                                        {                                             $Siteselect = "<div class="error_stage2">                                                                 Clanwar with clanwarid $cwid doesn't exist!                                                            </div>                                                          ";

}                              }                              break;                    }

echo $Siteselect; ?> [...]

die datei, in der die Clanwars stehen sieht in etwa so aus: 1| gegener|---|datum|---|ergebnis 2| gegener2|---|datum2|---|ergebnis2 3| gegener3|---|datum3|---|ergebnis3 4| gegener4|---|datum4|---|ergebnis4 [...]

ich hoffe ihr habt mein Problem verstanden um es nochmal zu zentrieren ich will aus einer Datei eine Zeile löschen! Sollte ihr eine andere Lösung haben um eine Zeile aus einer Datei zu löschen wäre auch darüber dankbar.

mfg nokill

  1. Hello,

    1. Schritt:
       Dein Script aufräumen und in vernünftige Funktionen aufteilen

    2. Schritt
       Die Funktion "delete_entry($filename,$entryname)" als Beispiel
       sollte dann alles leisten, was Du erreichen willst und wird
       schön übersichtlich bleiben.

    3. Schritt
       Poste dann diese Funktion hier nochmal mit genauer Fehlerbeschreibung
       sowie den Fehlertexten des Systems

    4. Schritt
       Wir werden dir die Funktion dann so zerpflücken, dass Du nie wieder
       vergisst, was alles falsch war ;-))

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

    Tom

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

      hier nochmal extra für dich mit Kommentaren und der Funktion delete_entry():

      //Konfigurationsdaten               $datei = "database/clanwars.dat"; #Dateipfad               $cwid  = $_GET['cwid']; #Clanwarid //Test ob Formular benutzt wurde               switch($_GET['action'])                    { //Auswahl des Clanwar, der geloescht werden soll                         default:                         $Siteselect = "-= Delete clanwar =-                                        <br />                                        <br />                                        <form action="$PHP_SELF" method="get">                                             <div>                                             Clanwarid:<input type="text" name="cwid">                                                       <input type="hidden" name="action" value="get">                                             </div>                                             <div>                                                   <input type="submit" name="go" value="Go">                                                   <input type="reset" name="Reset" value="Reset">                                             </div>                                        </form>                                       ";                              break; //wenn Clanwarid mit Formular eingegeben wurde //hier kommt jetzt also der interresante Teil                         case "get":                         if(file_exists($datei))                              {                                   $inh = file($datei,"r");                                   $anzahl = count($inh);                                   for($i = 0, $var = 1, $anzzeilen = 1; $i < $anzahl; $i++)                                        {                                             $eintrag     = explode("\n",$inh[$i]);                                             trim($eintrag['0']); //auslesen aller Zeilen in jeweils ein Array der variable $zeile                                             $zeile[$var] = $eintrag['0'];

      $var++; //Anzahl der Zeilen zaehlen                                             $anzzeilen++;

      echo "$anzzeilen<br>";                                        } //pruefen ob Clanwar mit entsprechender Clanwarid existiert                                   if ($cwid<=$anzzeilen)                                        { //loeschen der Zeile                                   function delete_entry ($filename, $entryname)                                   {                                       $filename  = $datei;                                       $entryname = $cwid;

      unset($zeile[$cwid]);                                             trim($zeile);                                             $newfp      = fopen($datei,"w"); //Alle zeilen in die Variable $newcontent schreiben und $newcontent dann in datei schreiben                                             $newcontent = implode("",$zeile);                                             fputs($newfp,$newcontent);                                             fputs($newfp,"\n");                                             fclose($newfp);                                   }

      $Siteselect = "v0.3 beta1                                                            <br />                                                            <br />                                                            <div class="success">                                                                 Clanwar deleted successfully!                                                            </div>                                                           ";                                        }                                   else                                        {                                             $Siteselect = "<div class="error_stage2">                                                                 Clanwar with clanwarid $cwid doesn't exist!                                                            </div>                                                          ";

      }                              }                              break;                    }

      delete_entry ("clanwars.dat", $cwid);


      ich hoffe das ganz ist jetzt übersichtlicher

      mfg nokill

      1. Hello,

        hier nochmal extra für dich mit Kommentaren und der Funktion delete_entry

        Bitte geh nochmal in dich, was ich Dir mit meinem Vorschlag wohl sagen wollte. Du lieferst hier einfach zuviel Code ab, in einem unmöglichen Format, also nur sehr schwer lesbar.

        Ich interessierte mich nur für die Funktion, die die Löschaufgabe hat.

        01 function delete_entry ($filename, $entryname)
        02 {
        03   $filename  = $datei;
        04   $entryname = $cwid;
        05   unset($zeile[$cwid]);
        06   trim($zeile);
        07   $newfp = fopen($datei,"w");
        08   //Alle zeilen in die Variable $newcontent schreiben und $newcontent dann in datei schreiben
        09   $newcontent = implode("",$zeile);
        10   fputs($newfp,$newcontent);
        11   fputs($newfp,"\n");
        12   fclose($newfp);
        13 }

        03 Woher kommt die Varibale $datei? Eine Funktion hat einen eigenen
           Namensraum. Du scheinst also keine Fehlermeldungen eingeschaltet
           zu haben, sonst müsstest Du mindestens eine Warnung bekommen
        04 dito.
           Außerdem überschreibst Du mit der Zuweisung dein Funktionsargument
           $entryname. Dann hättest Du es nicht zu übergeben brauchen.
        05 woher kommt das Array (oder der String) $zeile?
        06 Warum wird das Array mit trim() behandelt?
        07 damit wird die Datei $datei gelöscht, wenn sie vorhanden war, und
           als leere datei neu angelegt. Aber woher kommt $datei?
        08 Jede Zeile entspricht doch einem Datensatz. Wie trennst Du die
           Datensätze voneinander? Ich sehe keine Behandlung für das Zeilenende-
           zeichen (als Datensatztrenner).

        Keine Fehlerbehandlung
        Keine Dateisperrung, also kein sauberer Multiuserbetrieb möglich

        Generell! Die Funktion sollte folgendes leisten:

        Datei öffnen im nichtzerstörenden Modus
        Wenn sie nicht vorhanden war, anlegen
        Erfolgskontrolle
        Datei sperren mit Warten (ist für den Anfang einfacher...)
          Erfolgskontrolle hier nicht notwendig, weil die Sperrfunktion
          soweiso so lange wartet, bis sie erfolgreich war oder ScriptTimeout
        Dateizeiger auf Anfang
        Datei vollständig auslesen mit fread()
        Stream in Array umwandeln --> unserialize()
        Arrayelement löschen, wenn es vorhanden ist
        Array wieder in Stream umwandeln --> serialize()
        Dateizeiger auf Anfang
        Array wegschreiben
        Datei auf die Länge des Streams kürzen --> ftruncate
        Datei schließen (Sperre wird damit automatisch aufgelöst)
        Funktionsergenis zurückgeben --> return

        Jeder Zugriff auf die Datei muss mit Locking arbeiten, auch wenn Du nur lesen willst. Insbesondere muss für eine Veränderung von Daten die Datei innerhalb des LOCK vollständig gelesen und geschrieben werden. Alle anderen Varianten sind fehlerträchtig.

        Nun versuche bitte mal, meinen Pseudocode für die Funktion in PHP umzusetzen. Wenn es dabei dann noch Probleme gibt, stehe ich Dir gerne zur Verfügung.

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

        Tom

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

          hier mal nur das absolut wichtigste:
          ----------

          $datei = "clanwars.dat";
                        $cwid  = $_GET['cwid']; #hier wird eine Nummer aus einer Eingabe von user verwertet

          $inh = file($datei,"r");
                                            $anzahl = count($inh);
                                            for($i = 0, $var = 1, $anzzeilen = 1; $i < $anzahl; $i++)
                                                 {
                                                      $eintrag     = explode("\n",$inh[$i]);
                                                      trim($eintrag['0']);
                                                      $zeile[$var] = $eintrag['0'];

          $var++;
                                                      //alle zeilen zaehlen
                                                      $anzzeilen++;

          echo "$anzzeilen<br>";
                                                 }

          if ($cwid<=$anzzeilen)
                                                 {
                                                      unset($zeile[$cwid]);
                                                      trim($zeile);

          $newfp      = fopen($datei,"w");
                                                      for ($a = 1; $a < $anzzeilen; $a++)
                                                           {
                                                                trim($zeile[$a]);
                                                                $inhmbr = $zeile[$a]."\n";
                                                                trim($inhmbr);
                                                                echo $inhmbr;
                                                                fputs($newfp, $inhmbr);
                                                           }
                                                      fclose($newfp);

          echo "Erfolg";
                                                 }

          ----------

          aber inzwischen habe ich schon fast eine vollständig funktionierene Möglichkeit gefunden ich muss jetzt nur noch wissen wie man den Inhalt einer Datei löscht OHNE die Datei zu löschen hättest du da was?

          mfg nokill

          1. Hello,

            hier mal nur das absolut wichtigste:

            Immer noch in einem unmöglichen Format.
            Akzeptiere bitte, dass ich darauf nicht mehr antworte.
            Außerdem wollte ich nur die Funktion sehen.

            ich muss jetzt nur noch wissen wie man den Inhalt einer Datei löscht OHNE die Datei zu löschen hättest du da was?

            Darauf hatte ich Dir schon einen Hinweis gegeben.
            http://www.php.net/manual/de/function.ftruncate.php

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

            Tom

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

              hier mal nur das absolut wichtigste:

              Immer noch in einem unmöglichen Format.
              Akzeptiere bitte, dass ich darauf nicht mehr antworte.
              Außerdem wollte ich nur die Funktion sehen.

              ich muss jetzt nur noch wissen wie man den Inhalt einer Datei löscht OHNE die Datei zu löschen hättest du da was?

              Darauf hatte ich Dir schon einen Hinweis gegeben.
              http://www.php.net/manual/de/function.ftruncate.php

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

              Hoi Tom,

              ich offe wenn ich 3 Zeilen Code schreibe ist das übersichtlich ;)

              $inhmbr = $zeile[$a]."\n";
              trim($inhmbr);
              fwrite($newfp, $inhmbr);

              wenn ich hier jetzt $inhmbr mit "echo $inhmbr;" ausgebe habe ich folgendes Ergebnis:
              <<<<<<<<<
              zeile1
              zeile2
              zeile3
              ...

              wenn ich jetzt die Variable $inhmbr in die Datei mit fwrite($newfp, $inhmbr); schreiben will, dann steht das ganz so in der Datei:
              <<<<<<<<<
              zeile1

              zeile2

              zeile3

              ...

              es werden also ohne für mich ersichtlichen Grund hinter jeder Zeile ein weiterer Zeilenumbruch eingefügt. Ist das normal?

              p.s. wenn das so weiter geht steige ich auf MySql um ;)

              mfg nokill ich hoffe ich habe nicht unhöflich gewirkt war wrklich nicht meine Absicht

              1. Hello,

                ich offe wenn ich 3 Zeilen Code schreibe ist das übersichtlich ;)

                Wenn nun noch ein paar Kommentare dabei stünden? ;-)

                $inhmbr = $zeile[$a]."\n";

                Woher kommt $zeile[$a] ?
                Was ist $a?

                trim($inhmbr);

                Warum hängst Du das \n erst an $inhmbr dran, wenn Du es hier gleich
                wieder abschneidest?

                fwrite($newfp, $inhmbr);

                Wo stand denn der Dateizeiger, als Du den letzten Zugriff auf $newfp fertig hattest? In welchem Modus ist $newfp geöffnet worden?

                wenn ich hier jetzt $inhmbr mit "echo $inhmbr;" ausgebe habe ich folgendes Ergebnis:
                <<<<<<<<<
                zeile1
                zeile2
                zeile3
                ...

                wenn ich jetzt die Variable $inhmbr in die Datei mit fwrite($newfp, $inhmbr); schreiben will, dann steht das ganz so in der Datei:
                <<<<<<<<<
                zeile1

                zeile2

                zeile3

                ...

                Wo echo_st Du denn? Im Browser oder auf der Konsole?

                es werden also ohne für mich ersichtlichen Grund hinter jeder Zeile ein weiterer Zeilenumbruch eingefügt. Ist das normal?

                Das weiß ich nicht, weil cih nicht weiß, welches Betriebssystem Du benutzt und welchen Öffnungsmodus für die Datei du benutzt und was Du mit der Streamvariable sonst noch so anstellst.

                p.s. wenn das so weiter geht steige ich auf MySql um ;)

                Davon würde ich abraten, bevor Du nicht die einfachsten Dateioperationen sicher drauf hast.

                mfg nokill ich hoffe ich habe nicht unhöflich gewirkt war wrklich nicht meine Absicht

                Nein. Ein Lernprozess benötigt eben Zeit. Aber wenn man sich gegensetig helfen will, sollte man es dem Helfer nicht unnötig schwer machen, indem man zuviel zudem auch noch unförmigen Code schickt. Es trainiert auch die eigene Kombinationsgabe, wenn man nur den wirklich relevanten Teil rausschneidet, die Randbedingungen kurz aber verständlich erklärt und dann die Fragen stellt. Was Deinen Postings noch fehlt, sind die Fehlermeldungen des Systems. Die musst Du bitte demnächst auch mitposten, ok?

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

                Tom

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

                  damit es jetzt doch verständlicher wird ein paar mehr Zeilen Code:
                  ----------
                  1| $newfp = fopen($datei,"w");
                  2| fputs($newfp, "");
                  3| for ($a = 1; $a < $anzzeilen; $a++)
                  4| {
                  5|      trim($zeile[$a]);
                  6|      $inhmbr = $zeile[$a]."\n";
                  7|      trim($inhmbr);
                  8|      echo $inhmbr;
                  9|      fwrite($newfp, $inhmbr);
                  10| }
                  11| fclose($newfp);
                  ----------

                  Was ist $a?

                  Siehe Zeile 3

                  Warum hängst Du das \n erst an $inhmbr dran, wenn Du es hier gleich
                  wieder abschneidest?

                  Weil das trimmen anscheinend nicht funktioniert! (Das könnte daranliegen, dass man keine Arrays trimmen kann?)

                  Wo stand denn der Dateizeiger, als Du den letzten Zugriff auf $newfp fertig hattest? In welchem Modus ist $newfp geöffnet worden?

                  Am Datei Anfang

                  Wo echo_st Du denn? Im Browser oder auf der Konsole?

                  Browser

                  Das weiß ich nicht, weil cih nicht weiß, welches Betriebssystem Du benutzt und welchen Öffnungsmodus für die Datei du benutzt und was Du mit der Streamvariable sonst noch so anstellst.

                  Die ganz geschichte geschieht uter meinem Localhost (ich benutzt WinXp)

                  Was Deinen Postings noch fehlt, sind die Fehlermeldungen des Systems. Die musst Du bitte demnächst auch mitposten, ok?

                  Und wenn ich keine hatte?

                  mfg nokill

                  1. Hello,

                    Was Deinen Postings noch fehlt, sind die Fehlermeldungen des Systems. Die musst Du bitte demnächst auch mitposten, ok?
                    Und wenn ich keine hatte?

                    Gut, fangen wir hier hinten an.
                    Zur Entwicklung von PHP-Applikationen immer alle Fehlermeldungen einschalten:

                    in der php.ini display_errors = ON und track_errors = ON setzen und im Script gleich als erstes die Zeile error_reporting(E_ALL); einfügen. Dann solltest Du Fehlermeldungen sehen.
                    Darüberhinaus empfiehlt es sich manchmal noch, die Konstante DEBUG im Script einzuführen und dann

                    if (DEBUG)
                    {
                      $meinErrorText = ".....";
                      error_log (__LINE__.": $php_errormsg\n$meinErrorText"),
                                 3, "/var/tmp/php-errors.log");
                    }

                    Das würde dann nämlich auch funktionieren, wenn man display_errors mal absichtlich wieder auf off stellt, weil man header() Statements testen muss.

                    Lies Dir mal aufmerksam http://www.php.net/manual/de/ref.errorfunc.php durch. und nutze die Möglichkeiten.

                    Zweitens:

                    Du hast immer noch keinen sauberen Aufbau in Deinem Script. Trenne die Aufgaben streng voneinander. Machst Du eigentlich vorher keine Planung für ein Programm? Da gibt es sowas wie Programmablaufplan (PAP) oder Nassi-Shniderman-Diagramm oder Metachart-Planung mit Pseudocode (MP/P). Letzteres gefällt mir bei verteilten Anwendungen (Client-Server) am besten.

                    Wieviele Einträge wird Deine Datei bekommen?
                    Wenn sie zusammen nicht mehr als 1-2MB ergeben, dann kann man die Datei immer komplett einlesen. Das sollte man in einem Stück mit fread() tun, damit man das System nicht ausbremst - also bitte nicht in einer Schleife zeilenweise lesen!

                    Dann denk mal über das Format Deiner Daten im Hauptspeicher nach. Ein assoziatives Array erscheint mir hier doch am geeignetsten. Du hast einen Schlüsselwert, nach dem du suchst und kannst das Arrayelement daher in Nullkomanix finden, löschen, hinzufügen, verändern.

                    Dieses Array kannst Du dann komplett in deiner Datei abspeichern. Wie die Funktion aussehen muss dafür habe ich Dir schon gepostet. Du musst den Pseudocode nur noch in PHP gießen.

                    Nochmal zusammengefasst die Schritte, die du machen solltest:
                    1. Fehlerbehandlung und Logging einbauen und aktivieren
                    2. Programmplanung mit Papier, Bleistift und Radiergummi
                    3. Planung der Datenmodelle für RAM und DISK
                    4. Erstellung der Funktionen für
                       - Holen, suchen, anzeigen
                       - Holen, ändern, wegschreiben    der Daten
                    5. Zsammenbau der Funktionen nach Plan
                    6. Testen und Debugging
                    ---------------------------------
                    7. Spielen wie die Wildsau ;-))

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

                    Tom

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

                wenn ich hier jetzt $inhmbr mit "echo $inhmbr;" ausgebe habe ich folgendes Ergebnis:
                <<<<<<<<<
                zeile1
                zeile2
                zeile3
                ...

                wenn ich jetzt die Variable $inhmbr in die Datei mit fwrite($newfp, $inhmbr); schreiben will, dann steht das ganz so in der Datei:
                <<<<<<<<<
                zeile1

                zeile2

                zeile3

                ...

                Okay jetzt bin ich verwirrt! wenn ich die Datei im Editor  von Windows öffne dann passt alles!
                Muss ich das verstehen lag das an meinem HTML Editor?
                (ich benutze Phase5)

                mfg nokill

  2. Hallo,

    http://www.php-faq.de/q/q-datei-einfuegen.html

    Gruß, Thoralf

    --
    Sic Luceat Lux!