Löschen einer Zeile aus Datei
nokill
- php
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:
<? [...]
$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; }
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
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
Hi,
//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
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
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
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
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.phpLiebe 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
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:
<<<<<<<<<
zeile1zeile2
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
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
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
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:
<<<<<<<<<
zeile1zeile2
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