Zeile aus Datei entfernen, ohne Datei einlesen zu müssen.
Candid Dauth
- php
0 MudGuard0 Candid Dauth0 dedlfix0 Candid Dauth0 dedlfix
0 Daniel0 Tom
Heißa, Forum,
ich habe eine Datei, in der zeilenweise Werte drinstehen:
bla
moep
blubb
gautera
[…]
Nun soll ein PHP-Skript folgendes machen:
Es soll eine zufällige Zeile finden, deren Wert benutzen und die Zeile dann aus der Datei löschen, damit der Wert kein zweites Mal benutzt wird.
Das Problem ist nun, dass die Datei ziemlich groß ist (mehrere MB) und ich sie deshalb nicht komplett in den Speicher laden will. Eine zufällige Zeile herauszufinden ist nun kein Problem, ich nehme einfach an eine zufällige Position in der Datei (ermittelt per rand() und filesize()) und suche dann den nächstbesten Zeilenumbruch. Das Problem ist aber das Löschen der Zeile.
Im Chat habe ich mir sagen lassen, dass PHP hierfür keine Boardmittel mitbringt. Also wurde mir empfohlen, die Datei Stück für Stück auszulesen, auf diese Weise den Inhalt in eine andere Datei zu kopieren – bis eben auf die Zeile – und dann die Original-Datei mit der neuen zu überschreiben.
Das gefällt mir nur nicht ganz, denn es kann sein, dass das Script ziemlich oft aufgerufen wird, und das würde den Server recht stark belasten, wenn er ständig mehrere MB hin- und herkopieren müsste, nur um eine Zeile aus der Datei zu löschen.
Hat jemand von euch eine Idee, wie man das schön performant lösen könnte?
Gautera!
Grüße aus Biberach Riss,
Candid Dauth
Hi,
Es soll eine zufällige Zeile finden, deren Wert benutzen und die Zeile dann aus der Datei löschen, damit der Wert kein zweites Mal benutzt wird.
Das Problem ist nun, dass die Datei ziemlich groß ist (mehrere MB) und ich sie deshalb nicht komplett in den Speicher laden will. Eine zufällige Zeile herauszufinden ist nun kein Problem, ich nehme einfach an eine zufällige Position in der Datei (ermittelt per rand() und filesize()) und suche dann den nächstbesten Zeilenumbruch. Das Problem ist aber das Löschen der Zeile.
Nur mal so als Idee:
Erweitere die Suche nach dem nächsten Zeilenumbruch etwas, nämlich um die Suche nach dem nächsten Zeilenumbruch, dem kein weiterer Zeilenumbruch folgt.
Zum Löschen überschreibst Du dann die benutzte Zeile mit lauter Zeilenumbruchzeichen.
(wahlweise auch mit einem anderen, sonst nicht benutzten Zeichen überschreiben, dann halt die Suche nach der Zeile entsprechend anpassen)
Im Chat habe ich mir sagen lassen, dass PHP hierfür keine Boardmittel mitbringt. Also wurde mir empfohlen, die Datei Stück für Stück auszulesen, auf diese Weise den Inhalt in eine andere Datei zu kopieren – bis eben auf die Zeile – und dann die Original-Datei mit der neuen zu überschreiben.
Ist nicht so sehr ein PHP- wie ein Dateisystem-Problem: man kann nicht einfach mitten in einer Datei etwas rauslöschen.
cu,
Andreas
Heißa, MudGuard,
Erweitere die Suche nach dem nächsten Zeilenumbruch etwas, nämlich um die Suche nach dem nächsten Zeilenumbruch, dem kein weiterer Zeilenumbruch folgt.
Zum Löschen überschreibst Du dann die benutzte Zeile mit lauter Zeilenumbruchzeichen.
Okay, vielen Dank, so habe ich es jetzt gelöst. Ist zwar ein klein wenig umständlich, aber es funktioniert. :-)
Gautera!
Grüße aus Biberach Riss,
Candid Dauth
echo $begrüßung;
Erweitere die Suche nach dem nächsten Zeilenumbruch etwas, nämlich um die Suche nach dem nächsten Zeilenumbruch, dem kein weiterer Zeilenumbruch folgt.
Zum Löschen überschreibst Du dann die benutzte Zeile mit lauter Zeilenumbruchzeichen.Okay, vielen Dank, so habe ich es jetzt gelöst. Ist zwar ein klein wenig umständlich, aber es funktioniert. :-)
Mit dieser Methode suchst du dir mit zunehmenden Lösch-Überschreiben einen Wolf. Und wenn deine Zufallszahl hinter der letzten noch lebenden Zeile landet, dann findest du nichts mehr, obwohl ja doch noch was da ist.
Aber eine vernünftige dateibasierte Lösung fällt mir auch nicht ein, nur "Datenbank" kommt mir in den Sinn. Es muss ja nicht immer MySQL sein, es gibt da ja auch noch die Database (dbm-style) Abstraction Layer Functions, die ganz einfache Key-Value-Beziehungen verwalten können.
echo "$verabschiedung $name";
Heißa, dedlfix,
Mit dieser Methode suchst du dir mit zunehmenden Lösch-Überschreiben einen Wolf. Und wenn deine Zufallszahl hinter der letzten noch lebenden Zeile landet, dann findest du nichts mehr, obwohl ja doch noch was da ist.
Och, das habe ich schon hinbekommen. Wenn bis zum Ende der Datei nichts gefunden wird, wird vom Anfang an weitergesucht (eigentlich umgekehrt, es wird rückwärts nach Zeilenenden gesucht). Wenn überhaupt nichts gefunden wird, wird abgebrochen.
Klar, dann lese ich wieder die ganze Datei ein, aber wenn ich es so mache, wie Daniel es vorgeschlagen hat, dass die Datei einmal am Tag „geleert“ wird, ist das auch nicht mehr so problematisch.
Aber eine vernünftige dateibasierte Lösung fällt mir auch nicht ein, nur "Datenbank" kommt mir in den Sinn. Es muss ja nicht immer MySQL sein, es gibt da ja auch noch die Database (dbm-style) Abstraction Layer Functions, die ganz einfache Key-Value-Beziehungen verwalten können.
Hm, mir gefallen Textdateien besser. Über Datenbanken habe ich auch schon nachgedacht, aber bei meinem Webhoster steht mir nur MySQL zur Verfügung, und irgendwie kann ich das nicht leiden.
Deinen Link werde ich mir später noch anschauen, vielleicht ist das ja doch was.
Gautera!
Grüße aus Biberach Riss,
Candid Dauth
echo $begrüßung;
Database (dbm-style) Abstraction Layer Functions, die ganz einfache Key-Value-Beziehungen verwalten können.
Wenn ich nochmal so darüber nachdenke, sind die auch nicht so sehr geeignet, da man nach dem Löschen Lücken in den Keys hat. Man kann die nicht ohne Aufwand neu nummerieren. Damit wird der Zugriff wieder zum Glücksspiel. :-(
echo "$verabschiedung $name";
Ahoi Candid Dauth,
Hat jemand von euch eine Idee, wie man das schön performant lösen könnte?
nach reiflicher prüfung der Funktionen des Dateisystems
Komme ich zu folgendem ergebniss:
PS: zu deiner Signutar, ich bin Badner, kein Fussballfan und suche
deshalb keine Übernachtungsmöglichkeit im Großraum Stuttgart.
MfG
Heißa, Daniel,
PS: zu deiner Signutar, ich bin Badner, kein Fussballfan und suche
deshalb keine Übernachtungsmöglichkeit im Großraum Stuttgart.
Aha, und warum erzählst du mir das? ;-)
Gautera!
Grüße aus Biberach Riss,
Candid Dauth
Hello,
den Inhalt einer Datei zu lesen, ohne die Datei einzulesen ist nicht möglich.
Den Inhalt einer sequentiellen Datei mit freier Satzlänge zu ändern, speziell eine Zeile zu entfernen, ist nicht möglich, ohne die Datei umzukopieren.
Diese Aussagen beziehen sich immer auf die üblichen DO-Systeme.
Selbstverständlich gab es auch schon viele andere, die sich nicht durchsetzen konnten und gibt es auch noch ein paar andere für Spezialanwendungen, die dann aber auch teuer sind. Dabei ist das meiste daran heute nur noch Software...
Wenn Du hingegen eine Datei mit fester Satzlänge baust, kannst Du auf Datensätze über ihre physische Position (pseudo-physische Position) direkt zugreifen, sie ggf. als "gelöscht" markieren oder ihren Inhalt verändern. Das ist dann wahlfreier Zugriff auf den Satz.
Wenn es Dir also um Geschwindigkeit, und nicht um Datenmenge geht, dann solltest Du Dateien mit fester Satzlänge schreiben.
Harzliche Grüße vom Berg
esst mehr http://www.harte-harzer.de
Tom