scandir vs. readdir

In diesem Tutorial geht es ausschliesslich um das Einlesen von Verzeichnissen und Dateien.

Genauer: Um die richtige Verwendung von scandir und readdir!

Beide Funktionen verfolgen das gleiche Ziel, sie lesen ein Verzeichnis auf dem Webserver ein und geben die beinhaltenden Dateien zurück.
Jedoch funktionieren beide Funktionen anders.

Die Funktion scandir liest ein komplettes Verzeichnis ein und gibt ein Array zurück, dabei ist es möglich, das ergebnis anhand der zweiten Funktionvariablen zu sortieren.

Der Aufbau:
scandir ( string $directory [, int $sorting_order = 0 [, resource $context ]] )
$directory entspricht dem Pfad zum Verzeichnis
$sorting_order entspricht der Sortierreihenfolge und ist standardmässig 0 (aufsteigend sortieren)
$context ist lediglich für Streams gedacht und in diesem Tutorial nicht interessant

$dir    = '/tmp'; // das Verzeichnis as eingelesen werden soll
$files1 = scandir($dir); //einlesen ohne Sortierung
print_r($files1);

Array(
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)
$dir = '/tmp'; // das Verzeichnis as eingelesen werden soll
$files2 = scandir($dir, 1);//einlesen mit sortierung
print_r($files2);

Array(
    [0] => somedir
    [1] => foo.txt
    [2] => bar.php
    [3] => ..
    [4] => .
)

Die Funktion readdir benötigt, anders als scandir, ein vorher geöffnetes Verzeichnis. Das bedeutet, bevor readdir verwendet werden kann, muss ein Verzeichnishandler mit opendir erzeugt werden.

Der Aufbau von readdir:
readdir ([ resource $dir_handle ] )
$dir_handle entspricht dem mit opendir geöffnetem Verzeichnis, dies kann auch leer bleiben, dann wird das zuletzt geöffnete Verzeichnis verwendet

In unserem Beispiel wird ebenfals ein Array erzeugt. Jedoch ist bei readdir die Sortierung vom Server der Indikator für die Reihenfolge

$files1 = array();
if ($handle = opendir('/tmp')) {
    while (false !== ($file = readdir($handle))) {
        $files1[] = $file;
    }
    closedir($handle);
}
print_r($files1);
Array (
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)

Ergebnisse sind gleich, wo ist also der Unterschied

Richtig ist, das beide Ergebnisse eine gleiche Ausgabe erzeugen. Aber der Unterschied ist gravierend.
Dies liegt daran, dass scandir bereits alles macht, was readdir auch macht, jedoch führt es danach noch eine Sortierung durch.
Möchte man das mit readdir erklären, könnte es ungefähr so aussehen:

function dcms_scandir($dir,$sort = 0) {
    $files = array();
    if ($handle = opendir($dir)) {
        while (false !== ($file = readdir($handle))) {
            $files[] = $file;
        }
        closedir($handle);
    if($sort == 1) {
            arsort($files);
        } else {
            asort($files);
        }
    }
    return $files;
}
$files1 = dcms_scandir('/tmp');
print_r($files1);
Array
(
    [0] => .
    [1] => ..
    [2] => bar.php
    [3] => foo.txt
    [4] => somedir
)
$files2 = dcms_scandir('/tmp', 1);
print_r($files2);
Array
(
    [0] => somedir
    [1] => foo.txt
    [2] => bar.php
    [3] => ..
    [4] => .
)

Was ist nun besser?

In meinen Augen hat scandir nur einen einzigen Vorteil, aber dafür viele Nachteile. Während ich mit scandir lediglich ein Verzeichnis einlesen kann, kann es bei einer bestimmten Menge an Dateien schon zu einem Speicherproblem kommen.

Benötigt man nur den Verzeichnisbaum, so kann scandir tatsächlich von Vorteil sein, aber für produktives Arbeiten mit Verzeichnissen ist es völlig ungeeignet.

Hier eine Liste klarer Vorteile von readdir:

  • readdir funktioniert in Schleifen, d.h. ich kann diesen Einlesevorgang selbst unterbrechen
  • bei readdir kann ich direkt auf den Typen eingehen, also Verzeichnisse und Dateien separat zwischenspeichern, oder sogar Unterverzeichnisse einlesen
  • nur in readdir kann man direkt auf den Dateitypen eingehen,z.B. nur Bilder einlesen
  • readdir ist schneller (wenn auch nur gering)

Hier mal eine Funktion um bestimmte Dateitypen einzulesen

Diese Funktion ist so aufgebaut, das auch Unterverzeichnisse eingelesen werden können.

function dcms_readdir($dir,$type,$rekursiv = false) {
    $files = array();
    if ($handle = opendir($dir)) {
        while (false !== ($file = readdir($handle))) {
            if($file != '.' && $file != '..') {
                if(is_file($dir.'/'.$file)) {
                    $file = explode(".",$file);
                    $fileext = array_pop($file);
                    if(in_array($fileext,$type)) {
                        $files[] = implode(".",$file).'.'.$fileext;
                    }
                } elseif(is_dir($dir.'/'.$file) && $rekursiv) {
                    $subdir = dcms_readdir($dir.'/'.$file,$type,$rekursiv);
                    if(count($subdir)>0) {
                        $files = array_merge($files,$subdir);
                    }
                }
            }
        }
        closedir($handle);
    }
    return $files;
}
$files1 = dcms_readdir('/tmp',array('jpg','gif'));
// nur das Verzeichnis tmp nach Bilder mit der Dateiendung jpg oder gif durchsuchen
print_r($files1);
Array
(
    [0] => /tmp/bar.gif
    [1] => /tmp/foo.jpg
)
$files2 = dcms_readdir('/tmp',array('jpg','gif'),true);
// das Verzeichnis tmp und alle Unterverzeichnisse nach Bilder mit der Dateiendung jpg oder gif durchsuchen
print_r($files2);
Array
(
    [0] => /tmp/bar.gif
    [1] => /tmp/foo.jpg
    [2] => /tmp/somedir/foo.jpg
    [3] => /tmp/somedir/bar.gif
)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

You may use these HTML tags and attributes

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

But, it will became readable code