Enrico: Wieder einmal "Verzeichnis auslesen" :-(

Hallo,

Entschuldigt bitte, wenn ich Euch wieder einmal mit meinem Problem "Verzeichnis einlesen" bemühen muss, aber irgendwie bekomme ich den Code nicht richtig hin.

Das Problem noch einmal im Detail beschrieben:

Ich habe folgende Ordnerstruktur:

Ordner "pic/pic/klein/"
   |
   +--- Ordner 1
   |       |
   |       +--- Bild 1
   |       +--- Bild 2
   |       +--- Bild 3
   |
   +--- Ordner 2
           |
           +--- Bild 1
           +--- Bild 2
           +--- Bild 3

Ich will nun alle Elemente (Verzeichnisname und darin ehthaltene Bilder) in ein mehrdimensionales Array einlesen, das letztendlich folgenden schematischen Aufbau haben soll:

$ArrayVerzeichnis ['Name']['ORDNERNAME']['Bilder'] = Bild 1, Bild 2, Bild 3

Mit folgendem Code scheint das Auslesen des Verzeichnisses "pic/pic/klein" und die Zuordnung zu den jeweiligen Arrays zu funktionieren. Wohl gemerkt "scheint", da die Ausgabe nicht funktioniert:

function VerzeichnisEinlesen ($Verzeichnis)
{
  $Verzeichnis = @opendir ($Verzeichnis);

while ($Eintrag = @readdir())
  {
    if (eregi ("^.{1,2}$", $Eintrag))
      continue;

if (is_dir ($Eintrag))
    {
      $ArrayVerzeichnis ['Name'] = $Eintrag;
      eval ("$ArrayVerzeichnis ['Name']['" . $Eintrag . "']['Bilder'] = array ();");
      VerzeichnisEinlesen ($Verzeichnis.$Eintrag . "/");
    }
    else
      $ArrayVerzeichnis ['Name']['" . $Eintrag . "']['Bilder'] = $Eintrag;
  }

closedir ($Verzeichnis);
  return $ArrayVerzeichnis;
}

$ArrayVerzeichnis          = array ();
$ArrayVerzeichnis ['Name'] = array ();

$ArrayVerzeichnis ['Name'] = VerzeichnisEinlesen ("pic/pic/klein/");

//
// Debugging
//

for ($i = 0; $i < sizeof ($ArrayVerzeichnis ['Name']); $i++)
{
  echo "<b>Verzeichnis: " . $ArrayVerzeichnis ['Name'][$i] . "</b><br>";
}

Greife ich auf das mehrdimensionale Array nur falsch zu oder liegen (noch) andere Fehler vor ?

Gruss, Enrico

  1. Hello Enrico,

    mal den Sinn Deiner Aufgabe vernachlässigt...

    Aber schau Dir genau an, wann du auf Dateien und Verzeichnisse

    • über ein Handle zugreifst
    • über einen Namen zugreifst

    und überlege Dir, was da wohl der Unterschied sein könnte.
    Dann sollte sich Dein Problem schon auflösen.

    Harzliche Grüße aus http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
  2. Moin!

    function VerzeichnisEinlesen ($Verzeichnis)
    {
      $Verzeichnis = @opendir ($Verzeichnis);

    Eine Variable - zwei Funktionen. Das geht garantiert schief und ist böse...

    while ($Eintrag = @readdir())

    @ nie verwenden! Das unterdrückt die Fehlermeldungen - und du bist doch schließlich gerade auf Fehlersuche, oder?

    {
        if (eregi ("^.{1,2}$", $Eintrag))

    Naja, ob man hier einen regulären Ausdruck nehmen muß (ausgerechtet auch noch die langsame Version mit eregi - besser, weil schneller, ist preg_match).

    continue;

    if (is_dir ($Eintrag))
        {
          $ArrayVerzeichnis ['Name'] = $Eintrag;

    Wo kommt denn diese Variable plötzlich her? Bislang existierte sie in deiner Funktion jedenfalls nicht. Und die globale Variable kann auch nicht gemeint sein, denn die gibts in dieser Funktion noch gar nicht.

    eval ("$ArrayVerzeichnis ['Name']['" . $Eintrag . "']['Bilder'] = array ();");

    Eval() ist böse. Immer. Es gibt nur in 0,01% aller Anwendungsfälle wirklich einen Grund, eval() einzusetzen, der Rest kommt ohne aus.

    Außerdem: Bist du sicher, dass eval() einen korrekten Befehlsstring erhält? Ich habe das so meine Zweifel.

    VerzeichnisEinlesen ($Verzeichnis.$Eintrag . "/");

    Aha, der Versuch einer Rekursion. Aber leider: Die Funktion gibt einen Ergebniswert zurück, der hier (im Gegensatz zum Aufruf im Hauptprogramm) keiner Variablen zugewiesen wird - und folglich verloren geht.

    }
        else
          $ArrayVerzeichnis ['Name']['" . $Eintrag . "']['Bilder'] = $Eintrag;

    Hier ein Beispiel, wie man ohne eval() auskommen kann. Naja, zumindest ein Versuch - die Anzahl der Anführungsstriche sind grandios falsch, weshalb es wohl nicht funktionieren dürfte.

    }

    closedir ($Verzeichnis);
      return $ArrayVerzeichnis;
    }

    $ArrayVerzeichnis          = array ();

    Eine Variable zu deklarieren und mit "leer" vorzubelegen ist sehr lobenswert.

    $ArrayVerzeichnis ['Name'] = array ();
    $ArrayVerzeichnis ['Name'] = VerzeichnisEinlesen ("pic/pic/klein/");

    Der Variablen dann aber zuerst ein leeres Array und dann einen Funktionswert zuzuweisen ist irgendwie doppelt gemoppelt. Die erste Zeile darf gerne entfallen.

    //
    // Debugging
    //

    for ($i = 0; $i < sizeof ($ArrayVerzeichnis ['Name']); $i++)
    {
      echo "<b>Verzeichnis: " . $ArrayVerzeichnis ['Name'][$i] . "</b><br>";
    }

    Ich würde hier zum Debugging einfach folgendes vorschlagen:
    echo "<pre>";
    var_dump($ArrayVerzeichnis);
    echo "</pre>";

    Das zeigt dir auf einen Schlag den sämtlichen Inhalt deiner Variablen.

    Greife ich auf das mehrdimensionale Array nur falsch zu oder liegen (noch) andere Fehler vor ?

    Viele andere Fehler. Du siehst meine Bemerkungen ja.

    Ich würde die Funktion nochmal komplett einstampfen und neu bauen. Rekursive Funktionsaufrufe sind nett, machen vieles einfacher - nur funktionieren sollten sie auch. Mache dir klar, welche Informationen du an die Funktion übermitteln mußt, damit du _eine_ Verzeichnisebene (ohne die Unterverzeichnisse) ermitteln und als Array zurückgeben mußt.

    Und mache dir außerdem klar, in welcher Art diese Informationen im Array abgelegt werden sollen. Das ist nämlich mindestens genauso wichtig, sich hier nicht zu verhaspeln. Im Zweifel: Zeichnung machen! Papier und Bleistift gehören zu jedem guten Entwicklungswerkzeug dazu, und die Entwicklung einer rekursiven Funktion ist definitiv kein Pappenstiel - siehst du hoffentlich, sonst würde deine Version ja schon funktionieren.

    - Sven Rautenberg