Announcement

Collapse
No announcement yet.

CheckListBox soll Dateien von Unterordnern anzeigen oder nix

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • CheckListBox soll Dateien von Unterordnern anzeigen oder nix

    hallo leute,

    dank dem forum habe ich bisher folgende funktion genutzt, um in meine checklistbox nach auswahl eines ordners alle html-dateien des jeweiligen ordners aufzulisten.
    <br><br>
    <pre>
    function ReadDir(Path, Mask: string; ShowPath: boolean): TStringlist;
    var SRec: TSearchRec;
    SL: TStringList;
    begin
    SL := TStringList.Create;
    FindFirst(Path + Mask, not faDirectory, SRec);
    if ShowPath then
    SL.Add(Path + SRec.Name)
    else
    SL.Add(SRec.Name);
    while FindNext(SRec) = 0 do
    if ShowPath then
    SL.Add(Path + SRec.Name)
    else
    SL.Add(SRec.Name);
    FindClose(SRec);
    Result := SL;
    end;
    </pre>
    <b>nun meine fragen und probleme:</b>
    <li>wenn in dem ausgewählten ordner keine html-dateien sind, listet die checklistbox den ordner selbst auf. das will ich aber nicht. (unter Win NT ist das problem schlimmer, denn da komme ich erst aus dem form wieder raus, wenn ich einen ordner habe,in dem sich html-dateien befinden)
    <li>ich möchte gern noch eine zusätzliche checkbox einbinden bei der der user entscheiden kann, ober er alle folgenden unterordner mit durchsuchen will und die gefundenen dateien auch mit auflisten.
    <br><br>
    danke für eure mithilfe
    <br><br>
    tom

  • #2
    Guten Morgen.

    1. Vielleicht hab´ ich´s nur übersehen: aber irgendwie vermisse ich die Freigabe der TStringList. Aber du könntest auch auf die TStringList verzichten und die Dateinamen gleich in die CheckListBox eintragen lassen.

    2. Du solltest grundsätzlich prüfen, ob <b>FindFirst</b> als Ergebnis auch Null zurückliefert. Ist das nicht der Fall, ist bereits an dem Punkt die Suche fehlgeschlagen.

    3. Das Durchsuchen von Unterverzeichnissen ist recht einfach, wenn du die Funktion einfach durch sich selbst aufrufen lässt. Dazu musst du aber a) ein anderes Attribut anstelle von "not faDirectory" benutzen (schließlich sollen Ordner ja berücksichtigt werden!), und wenn du einen Ordner gefunden hast, musst du prüfen, dass sein Name nicht "." oder ".." ist. Erst dann kannst du da reinspringen und die Funktion wieder aufrufen, damit sie die Dateien im Unterverzeichnis liest.

    Ach ja: wenn die Funktion nichts mehr findet, und der angegebene Pfad ("Path"-Variable) nicht mit dem tatsächlichen Verzeichnis ("GetCurrentDir") identisch ist, dann solltest du wieder eine Ebene nach oben springen ("ChDir('..')"), damit die Suche weitergehen kann.

    Gruß,
    Mathias

    Comment


    • #3
      hi mathias,
      <br><br>
      danke für deine antworten.
      <br><br>
      zu 1.<br>
      so wie ich das sehe, hat sich das vergessen der freigabe, in dem falle wohl <b>sl.free</b>, wie ein roter faden durchgezogen. aber so ist das nun mal, wenn man nich t in der lage ist selbst eine funktion zu entwickeln. so kam es, dass ich die funtkion einfach nur eingebunden habe und nicht darauf geachtet habe. ich ändere es aber noch.
      <br><br>
      zu 2.<br>
      kann ich als mitten in die funktion eine if-then-abfrage einbinden ? und würde es dann so gehen ?<br>
      <pre>
      FindFirst(Path + Mask, not faDirectory, SRec);
      if FindFirst = 0 then Exit
      </pre>
      <br><br>
      zu 3.<br>
      wenn ich nun den user an einer checkbox die option "incl. Unterverzeichnisse" anhacken lasse, muss ich dann eine 2. und somit andere bzw. modifizierte funktion aufrufen oder wie meinst du das ? denn ich will ja grundsätzlich nur die dateien des aktuellen ordners und im speziellen alle sich darunter befindlichen ordner mit einbeziehen.
      <br><br>
      zu ach ja:<br>
      wenn die funtkion nichts mehr findet, warum soll ich dann eine ebene höher gehen ? ich dachte ich soll, wenn ich das denn hinbekomme, ebene für ebene tiefer gehene und wenn nix mehr gefunden wird einfach die suche beenden ?
      <br><br>
      oder hab ich dich falsch verstanden ?
      <br>
      danke für deine geduld mit mir
      <br><br>
      to

      Comment


      • #4
        zu 1: Kein Problem. Ich hab´s anfangs auch nicht anders gemacht und mir Funktionen, die ich brauchte, bloß kopiert. ;o)

        zu 2: Du darfst nicht nach Null abfragen! Null bedeutet, dass es geklappt hat. Wenn du mit Null arbeiten willst, müsste es z.B. so aussehen:

        <pre><b>if</b> FindFirst(Path + Mask, <b>not</b> faDirectory, SRec) = 0 <b>then</b>
        <b>begin</b>
        <b>if</b> ShowPath <b>then</b>
        ...<br><br>
        <b>while</b> FindNext(Srec) = 0) <b>do</b>
        ...
        <b>end</b>
        </pre>

        Ich persönlich (das habe ich in der Delphi-Praxis schon mal gesagt) bevorzuge seit TurboPASCAL-Zeiten so eine Konstruktion:

        <pre><b>var</b>
        res : integer;<br><br>
        <i>{ ... }</i><br><br>
        res := FindFirst('*.*',faAnyFile,ds);
        <b>while</b>(res = 0) <b>do</b>
        <b>begin</b>
        <i>// mach was</i><br><br>
        res := FindNext(ds);
        <b>end</b>;
        FindClose(ds);</pre>

        Dürfte letztlich aber nur Ansichtssache sein.

        zu 3: Schau mal hier rein:
        http://www.delphipraxis.de/viewtopic.php?t=507
        . Da findest du das Prinzip, das ich meine. Die Funktion "scanit" ruft sich immer wieder selbst auf, wenn sie einen Ordner gefunden hat. Das Prinzip ist allerdings ein anderes: da geht´s nur darum, <b>eine</b> bestimmte Datei zu finden und dann die Suche abzubrechen. Ich denke aber, du müsstest aber auch hier im EF fündig werden, denn IMHO liegen <b>FindFirst</b>/<b>FindNext</b>-Anfragen doch etwas länger zurück und dürften nicht vom Daten-GAU betroffen sein.

        zu ach ja: Das Problem ist, dass z.B. der Windows-Explorer die Anzeige von Dateien und Verzeichnissen ordnet. Das hat aber nichts mit der tatsächlichen Anordnung auf der Platte zu tun. Da kann es passieren, dass erst mal zwei Dateien gefunden werden, dann wieder ein Ordner, dann wieder eine Datei ... usw.

        Wenn du also in einen Ordner springst, dann durchsuchst du den, springst dann aber wieder eine Ebene nach oben, damit das Programm evtl. noch weitere Unterordner durchsuchen kann. Ansonsten steckt es in so einem Unterordner fest, und die Suche geht nicht weiter.

        Gruß,
        Mathias

        Comment


        • #5
          hi mathias,

          danke für deine antworten. mir ging natürlich wieder mal ein licht mehr auf, als du schriebst, das ich zwar nach unten suchen muss aber den weg wieder zurück zu gehen haben, da es ja mehrere unterordner geben könnte und ich sonst nur einen einzigen hätte. ziemlich beschränkt. naja.
          <br><br>
          das mit der funktion muss ich erstmal noch durchtesten. bin zurzeit auf arbeit und kann nicht ganz so wie ich will. -))
          <br><br>
          sicher melde ich mich noch mal, wenn ich nicht klar komme.
          ciao
          to

          Comment


          • #6
            guten morgen mathias,

            ich habe im easy delphi helper genau die routine gefunden, welche ich als die richtige erachte. aber => siehe unten

            <pre>
            procedure GetFilesInDirectory(Directory: String; const Mask: String;
            List: TStrings;
            WithSubDirs, ClearList: Boolean);

            procedure ScanDir(const Directory: String);
            var
            SR: TSearchRec;
            begin
            if FindFirst(Directory + Mask, faAnyFile - faDirectory, SR) = 0 then try
            repeat
            List.Add(Directory + SR.Name)
            until FindNext(SR) <> 0;
            finally
            FindClose(SR);
            end;

            if WithSubDirs then begin
            if FindFirst(Directory + '*.*', faAnyFile, SR) = 0 then try
            repeat
            if (SR.Attr = faDirectory) and
            (SR.Name <> '.') and (SR.Name <> '..') then
            ScanDir(Directory + SR.Name + '\');
            until FindNext(SR) <> 0;
            finally
            FindClose(SR);
            end;
            end;
            end;

            begin
            List.BeginUpdate;
            try
            if ClearList then
            List.Clear;
            if Directory = '' then Exit;
            if Directory[Length(Directory)] <> '\' then
            Directory := Directory + '\';
            ScanDir(Directory);
            finally
            List.EndUpdate;
            end;
            end;

            Ein Beispielaufruf könnte so aussehen:

            procedure TForm1.Button1Click(Sender: TObject);
            begin
            GetFilesInDirectory('C:\', '*.html', Listbox1.Items, False, True);
            end;
            </pre>
            <br><br>
            was mir noch nicht gefällt, ist zum
            <br><br>
            1. das die suche lang dauert und bei der suche das programm nix macht, zumindest macht es bei such von c:\ abwärts den eindruck, dass das programm abgeschmiert ist, da es doch eine ganze weile dauert, bis ein ergebnos da ist.
            <br><br>
            meine frage: kann man hier eine animation laufen lassen, da ich glaube, dass eine progressbar hier nicht sinnvoll ist, da ja der maxwert unbekannt ist !? oder eventuell den aktuell zu durchsuchenden ordner an einen label übergeben, damit der user sieht, wo sich das programm gerade befindet. was würdest du für sinnvollerachten !?
            <br><br>
            2. ruft man ja die procedure so auf:
            <pre>
            GetFilesInDirectory('C:\', '*.html', Listbox1.Items, False, True);
            end;
            </pre>
            ich möchte aber, dass nicht nur nach html sondern auch nach htm gesucht wird. hierzu habe ich frecherweise die procedure einfach 2 mal hintereinander aufgerufen. einmal mit html und einmal mit htm. leider hing sich dabei das programm auf. hast du einen besseren vorschlag !???
            <br><br>
            wieder mal in deiner schuld stehend
            tom
            <br><br&gt

            Comment


            • #7
              Hallo.

              zu 1. Man könnte schon einen Progressbar machen. Das habe ich in einem Programm mal ausprobiert. Allerdings ist das sozusagen "doppelt gemoppelt", weil ich vor dem eigentlichen Scannen das jeweils aktuelle Verzeichnis einmal durchgehe und den Max-Zähler bei jeder gefundenen Datei erhöhe. ;o)

              Dadurch hängt der Progressbar immer kurz vor dem Ende, erreicht es aber erst beim Beenden der Suche tatsächlich.

              Die bessere Alternative wäre in deinem Fall vielleicht, dass du den Cursor auf die Sanduhr änderst und vielleicht den jeweils aktuellen Datei- und/oder Verzeichnisnamen in einem Label anzeigen lässt. So sieht der User, dass noch was passiert.

              zu 2. Von der Syntax her scheint der Aufruf zu stimmen. Aber kann es sein, dass du dich da ein bisschen verrannt hast? In meinem EDH sieht die Funktion nämlich so aus:

              <pre><b>procedure</b> GetFilesInDirectory(ADirectory: <b>string</b>; AMask: <b>String</b>; AList: TStrings; ARekursiv: Boolean);
              <b>var</b>
              SR: TSearchRec;
              <b>begin</b>
              <b>if</b> (ADirectory&lt;&gt;'') <b>and</b> (ADirectory[length(ADirectory)]&lt;&gt;'\') <b>then</b>
              ADirectory:=ADirectory+'\';<br /><br />
              <b>if</b> (FindFirst(ADirectory+AMask,faAnyFile-faDirectory,SR)=0) <b>then</b> <b>begin</b>
              <b>repeat</b>
              <b>if</b> (SR.Name&lt;&gt;'.') <b>and</b> (SR.Name&lt;&gt;'..') <b>and</b> (SR.Attr&lt;&gt;faDirectory) <b>then</b>
              AList.Add(ADirectory+SR.Name)
              <b>until</b> FindNext(SR)&lt;&gt;0;
              FindClose(SR);
              <b>end</b>;<br /><br />
              <b>if</b> ARekursiv <b>then</b>
              <b>if</b> (FindFirst(ADirectory+'*.*',faDirectory,SR)=0) <b>then</b>
              <b>begin</b>
              <b>repeat</b>
              <b>if</b> (SR.Name&lt;&gt;'.') <b>and</b> (SR.Name&lt;&gt;'..') <b>then</b>
              GetFilesInDirectory(ADirectory+SR.Name,AMask,AList ,True);
              <b>until</b> FindNext(SR)&lt;&gt;0;
              FindClose(SR);
              <b>end</b>;
              <b>end</b>;</pre>

              Bei dir sind noch irgendwelche anderen Fragmente drin. Möglicherweise erklärt das die "Hänger". )

              Also, die "scandir"-Prozedur kannst du weglassen. Die Originalfunktion aus dem EDH tut´s auch.

              Gruß,
              Mathias

              Comment


              • #8
                hi mathias,

                das mit dem scanit fliegt natürlich raus. ich weiss auch nicht, wie das da rein kam. -(
                <br><br>
                ok das mit dem cursor werde ich sicher noch hinbekommen -)). wo aber steht denn, wo sich der suchzeiger gerade befindet ? foldenes würde ich probieren modifikationen in blau:
                <pre>
                procedure GetFilesInDirectory(ADirectory: string; AMask: String; AList: TStrings; ARekursiv: Boolean);
                var
                SR: TSearchRec;
                begin
                if (ADirectory<>'') and (ADirectory[length(ADirectory)]<>'\') then
                ADirectory:=ADirectory+'\';
                if (FindFirst(ADirectory+AMask,faAnyFile-faDirectory,SR)=0) then begin
                repeat
                if (SR.Name<>'.') and (SR.Name<>'..') and (SR.Attr<>faDirectory) then
                <font-color=blue>
                begin
                Label.caption:=(ADirectory+SR.Name);
                AList.Add(ADirectory+SR.Name);
                end;
                until FindNext(SR)<>0;
                FindClose(SR);
                end;
                if ARekursiv then
                if (FindFirst(ADirectory+'*.*',faDirectory,SR)=0) then
                begin
                repeat
                if (SR.Name<>'.') and (SR.Name<>'..') then
                GetFilesInDirectory(ADirectory+SR.Name,AMask,AList ,True);
                until FindNext(SR)<>0;
                FindClose(SR);
                end;
                end;
                </pre&gt

                Comment


                • #9
                  hi mathias,

                  natürlich fliegt die scandir-precedure noch raus. aber was ist mit dem problem der 2 dateiendungen (*.html|*.htm) ? wie kann ich denn das sicherstellen ?

                  to

                  Comment


                  • #10
                    Du könntest den Aufruf versuchen:

                    <pre>GetFilesInDirectory('c:\LastCrap','*.htm*',Li stbox1.Items,true);</pre>

                    Damit sollten alle Dateien mit der Endung "*.htm" und "*.html" berücksichtigt werden. Wenn du "*.*htm*" benutzt, dann werden z.B. auch ".shtml"-Dateien aufgelistet. Hoffe ich jedenfalls ;o), probiert hab´ ich´s jetzt nämlich nicht.

                    Gruß,<br>
                    Mathias

                    Comment


                    • #11
                      hi mathias,

                      das hier funzt *.*htm* einwandfrei.
                      nun muss ich nur den string finden, den ich an das label übergeben will.

                      to

                      Comment


                      • #12
                        hi mathias,

                        nun habe ich zumindest bei der rekursiven suche folgendes an das label anz_dir übergeben.

                        <pre>
                        Anz_dir.Caption:=(ADirectory+SR.Name);
                        </pre>
                        es passiert sogar was. alles ruckelt und zuckt. und da dass label auf autosize steht, sieht man sogar, wie das formular ab und zu scrollbalken erhält und verliert. aber der inhalt des labels selbst ist zu keinem zeitpunt lesbar.

                        ps.: autosize schalte ich jetzt natürlich wieder ab.

                        hast du einen vorschlage oder eine idee, warum der inhalt nicht angezeigt wird ? ich lasse mir jetzt erstmal per showmessage((ADirectory+SR.Name); alles anzeigen.

                        tja und wenn ich das tue, ist der inhalt in der box der richtige und im label steht auch alles richtig drin. ich habe eher den eindruck, dass label bzw. das form es nicht schafft so schnell zu schreiben oder gezeichnet zu werden.

                        ist da was dran ?

                        ciao to

                        Comment


                        • #13
                          Ich denke mal: Ja. Und ist doch auch gut. Stell dir vor, die Suchroutine wäre so lahm, dass du jeden gefundenen Namen sehen kannst. )

                          Letzten Endes ist es doch nur so eine Art Statusbericht für den User, damit der sieht: Aha, da passiert noch was. Das Ergebnis (sprich: die Dateinamen) hast du dann ja in der List- oder Checkbox.

                          Gruß,
                          Mathias

                          Comment

                          Working...
                          X