Mailinglisten-Archive |
Pascal Schult wrote: > jezt soll ein script ein verzeichnis öffnen, dies auslesen und nach- > einander die enthaltenen files öffnen, auslesen in einen string packen > und dann in ein neues file in einem anderen verzeichnis schreiben. > klappt auch wunderbar. jedoch schafft dieses script nur ca. 6 files Da fragt man sich natürlich, warum Du kein Systemkommando benutzt... > hmm, laeuft hier auf nem wxmp (win98, xitami, mysql, php3.11) Bei mir ist es gerade die Kommandozeile mit einem 3.0.11. > aber soweit kommt es nicht. flush() ist doch nur dafür da, daß alles an > den browser übergeben wird, schon bevor das script fertig ist, oder? Ja. Und damit ist es super geeignet Statusmeldungen auszugeben, bevor das Skript eines Todes stirbt. > mails in dieser liste, aber hier der quellcode: Puh, den will ich auch gar nicht mehr sehen. Laß uns noch mal ganz vorne anfangen. Aufgabe: kopiere alle Files eines Quellverzeichnisses in ein Zielverzeichnis. Bei kleineren Aufgaben beginne ich gleich mit dem Hauptprogramm. Ich schreibe auf, wie mein Programm aussehen soll. Dabei verwende ich Funktionen, die es noch gar nicht gibt. Ich mache mir also ein Bild der Legosteine, die ich gerne hätte. An den Code spiele ich so lange, bis ich ein Gefühl dafür habe, welche Legosteine mir die Arbeit besonders gut erleichtern könnten. <?php $source_dir = "f:/tmp/tmp/"; # Quellverzeichnis $dest_dir = "f:/tmp/tmp/new/"; # Zielverzeichnis $files = get_files($source_dir); # Dateien im Quellverzeichnis ermitteln if (!is_array($files) || 0==count($files)) exit; $status = array(); reset($files); while (list(, $file)=each($files)) { $source = $source_dir.$file; # Quelldatei $dest = $source_dir.$file; # Zieldatei out(file_copy($source, $dest)); # kopieren } ?> Hier wurden drei Legosteine eingeführt: array get_files( string $dirname ) string file_copy ( string $source, string $dest) void out ( string $text ) Die Funktion get_files() muß zunächst überprüfen, ob sie mit dem Namen eines Verzeichnisses aufgerufen wurde (is_dir()). Danach wird das Verzeichnis ausgelesen. Verzeichniseinträge vom Typ file (is_file) werden in einem Array gespeichert, alle anderen werden ignoriert. Dies verhindert, daß beim späteren kopieren versucht wird Directories, Links und ähnliches zu verarbeiten. <?php // array get_files ( string $dirname ) function get_files($dirname) { if (!is_dir($dirname)) return false; $h = opendir($dirname); if (!$h) return false; $files = array(); while ($file = _(at)_readdir($h)) if (is_file($dirname.$file)) $files[$file] = $file; return $files; } // end func get_files ?> file_copy() ist recht gesprächig. An fast jeder Stelle an der ein Fehler abgefangen werden kann, wird dies gemacht und die Funktion mit einer Fehlermeldung beendet. Anders als im Originalskript wurde in diesem Beispiel fread() benutzt. Immer, wenn man alle Inhalte aus einer Datei benötigt und auf eine zeilenweise Verarbeitung verzichten kann sollte fread() benutzt werden. fread() ist erheblich schneller, als das zeilenweise einlesen. unset() wird überhaupt nicht benutzt, weil mit lokalen Variablen gearbeitet wird und sich PHP um die Speicherfreigabe kümmert. <?php // string file_copy ( string $source, string $dest ) function file_copy($source, $dest) { if (""==$source || ""==$dest) return "Quelle oder Ziel nicht angegeben"; if (!file_exists($source)) return "Quelldatei '$source' existiert nicht"; if (file_exists($dest) && !is_writeable($dest)) return "Zieldatei existiert und kann nicht überschrieben werden"; $fh = _(at)_fopen($source, "r"); if (!$fh) return "Quelldatei '$source' kann nicht gelesen werden"; $daten = fread($fh, filesize($source)); fclose($fh); $fh = _(at)_fopen($source, "w"); if (!$fh) return "Zieldatei '$dest' kann nicht geöffnet werden"; if (!_(at)_fwrite($fh, $daten)) return "In der Zieldatei '$dest' konnten keine Daten gespeichert werden"; fclose($fh); return ""; } // end func file_copy ?> out() letztlich ist für die Ausgabe von Meldungen zuständig. Normalerweise wartet PHP mit der Ausgabe von Text bis das Ende des Skripts erreicht ist. Manchmal will man jedoch schon vorher Statusmeldungen sehen, um zu erfahren welcher Programmteil verarbeitet wird. Dies ist auch sehr wichtig bei langen Laufzeiten, damit der Browser keinen Timeout meldet. flush() leert den Ausgabepuffer und schickt die Daten direkt an den Client. function out($text) { echo "$text<br>\n"; flush() } it obigen Snippets kann man zwar ein übersichtliches Programm schreiben, aber kein gutes. Das Programm setzt vorraus, daß während der gesamten Laufzeit keine Änderungen an den Verzeichnissen vorgenommen werden. Besser wäre es, den Ablauf zu verändern und Filelocking zu benutzen (flock()): - öfffne Verzeichnis - lese Eintrag - verarbeite Eintrag - schließe Verzeichnis Noch besser ist es, die Systemfunktionen mit einem copy zu beauftragen... Und warum war das alte Skript jetzt abgestürzt. Ich tippe mal, daß es nicht erlaubt ist im Windows Desktopverzeichnis zu werkeln. Ulf
php::bar PHP Wiki - Listenarchive