Hallo,
So ich habe nun mal was "gebastelt".
sehr schön, und ich erlaube mir noch etwas gut gemeinte Kritik.
Dein Ansatz hat vor allem eine konzeptbedingte Einschränkung: Er setzt voraus, dass die Datei klein genug ist, um sie mit PHP vollständig in den verfügbaren Arbeitsspeicher zu laden. Bei Dateigrößen im Bereich von Megabytes ist die Gefahr groß, dass dem Script dann der Speicher ausgeht.
Wenn man das vermeiden will, muss man aber ganz anders ansetzen, etwa blockweise oder zeilenweise lesen. Das ist insgesamt etwas mehr Aufwand, lohnt sich aber, wenn man sich daraus eine universell verwendbare Funktion stricken will.
//gesamte Datei einlesen
$fp = fopen( $source_file, 'r');
$string1 = fread($fp, filesize($source_file));
fclose($fp);
Alles klar, $string1 enthält nun den gesamten Dateiinhalt (falls das Script nicht schon hier wegen Speichermangel beendet wurde).
$startblock = strpos($string1, $begin_area); //Position bis zum Beginn des Bereichs der ausgetauscht werden soll
$endblock = strpos($string1, $end_area); //End Position des Bereichs der ausgetauscht werden soll
$beginreadend = $endblock + strlen($end_area); //Endpostions plus der Länge der Zeile dazu addieren
Die Variable $endblock finde ich irreführend benannt, weil sie eben noch nicht das Ende des Blocks bezeichnet. Ich hätte daher die letzten beiden Zeilen zu einer zusammengefasst und mir dadurch eine unnötige und damit verwirrende Variable gespart.
$fp = fopen( $source_file, 'r');
$string2 = fread($fp, $startblock);//Alles einlesen bis zum Beginn des Blocks der ausgetauscht werden soll.
fseek ( $fp, $beginreadend, 'SEEK_CUR' );//Neues Handle setzen
$endcontent = fread($fp, filesize($source_file));//Rest nach Block bis Dateiende einlesen
fclose($fp);
Du öffnest und liest die Datei ein zweites Mal, obwohl du doch in $string1 schon den gesamten Inhalt hast. Mit substr() hättest du die beiden Teile einfacher und effizienter als mit einem erneuten Dateizugriff.
Übrigens hast du bis hierher (fast) den gesamten Dateiinhalt schon doppelt im Arbeitsspeicher.
$modifiedstring = $string2 . $newcontent . $endcontent; //Neuen String zusammensetzen
Und hier zum dritten Mal. Dein Speicherbedarf ist also grob gesagt dreimal so groß wie nötig.
// Sichergehen, dass die Datei existiert und beschreibbar ist
if (is_writable($source_file)) {
Das ist gut!
if (!$handle = fopen($source\_file, "w")) { print "Kann die Datei $filename nicht öffnen"; exit; } // Schreibe $somecontent in die geöffnete Datei. if (!fwrite($handle, $modifiedstring)) { print "Kann in die Datei $filename nicht schreiben"; exit; } print "Fertig, in Datei $filename wurde $somecontent geschrieben"; fclose($handle);
} else {
print "Die Datei $filename ist nicht schreibbar";
}
Endlich mal jemand, der sich auch um mögliche auftretende Fehler kümmert! Wobei ... du hast anfangs nicht überprüft, ob die Originaldatei überhaupt existiert.
Was meint ihr, umständlich oder kann man es so lassen?
Etwas umständlich auf jeden Fall, vor allem wegen des doppelten Lesens und des dreifachen Pufferns.
Das einzge ist das in der neuen (modifizierten Datei) keine CRLF sondern nur LF drin sind.
Nanu? Die unveränderten Bereiche am Anfang und am Ende schreibst du doch auch wieder in die Ausgabedatei, ohne sie zu verändern. Da dürfte also keine Änderung auftreten. Beim neu hinzugekommenen bzw. editierten Bereich kommt's drauf an, wie du ihn aufbereitest: Setzt du als Zeilenumbrüche nur \n (LF) ein, oder notierst du \r\n (CR+LF)?
Aber ich denke das ist nicht so tragisch oder?
Im Unix-Bereich ist \n als Zeilenumbruch üblich, im Windows-Bereich \r\n. Die meisten Programme können aber mittlerweile mit beiden Varianten umgehen. Für normale Textdateien ist das daher nebensächlich. Nur wenn beide Formen gemischt in einer Datei auftreten, könnte es etwas Durcheinander geben.
Und wenn die bearbeitete Datei später in einem Kontext verwendet wird, wo eine bestimmte Notation vorgeschrieben ist, muss man auch darauf achten.
So long,
Martin
PCMCIA: People Can't Memorize Computer Industry Acronyms