amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > Rekrusives durchsuchen von Verzeichnissen [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

27.01.2008, 22:21 Uhr

Ralf27
Posts: 2779
Nutzer
Ich hab folgenden Code, der leider wohl das System instabil macht:
code:
DEFINT a-z
REM $INCLUDE Exec.bh
REM $INCLUDE DOS.bh
REM $INCLUDE Intuition.bh
LIBRARY OPEN "dos.library"
LIBRARY OPEN "intuition.library"
LIBRARY OPEN "exec.library"

CONST MaxSkins=200
CONST MaxEbenen=10:REM maximale Verzeichnisstiefe
CONST MaxDirs=100 :REM maximale Anzahl Verzeichnisse pro Verzeichniss

DIM Skin$(MaxSkins,1)
DIM DIR$(MaxEbenen,MaxDIRs),DIRCount(MaxDIRs),DirNr(MaxDIRs)

SCREEN 1,640,512,1,4
WINDOW 2,,,128,1

 ASkins=0
 FIBlock&=AllocVec&(FileInfoBlock_sizeof%,MEMF_PUBLIC&)
 DIR$(0,0)="Daten"
 DIRCount(0)=0
 DIRNr(0)=0
 Ebene=1
 WHILE Ebene
  v$=""
  FOR x=0 TO Ebene-1
   v$=v$+DIR$(DIRCount(x),x)
   IF x<Ebene-1 THEN v$=v$+"/"
  NEXT
  PRINT v$
  FileLock&=Lock&(SADD(v$+CHR$(0)),ACCESS_READ&)
  IF FileLock&=0 THEN
   Var$=STR$(IOErr$)
   PRINT "Fehler_SkinlisteLaden"
   Ebene=0
  ELSE
   Status=Examine(FileLock&,FIBlock&)
   WHILE Status
    Status=ExNext(FileLock&,FIBlock&)
    IF Status THEN
     FileName$=PEEK$(FIBlock&+fib_FileName%)
     IF PEEKL(FIBlock&+fib_DirEntryType%)>0 THEN
      PRINT "(verzeichniss)"FileName$
      INCR DIRNr(Ebene)
      DIR$(DIRNr(Ebene),Ebene)=FileName$
     ELSE
      PRINT"(file)"FileName$
      IF RIGHT$(FileName$,4)=".dat" THEN
       INCR ASkins
       Skin$(ASkins,0)=MID$(FileName$,1,LEN(FileName$)-4)
       Skin$(ASKins,1)=v$+"/"
      END IF
     END IF
    END IF
   WEND
   UnLock FileLock&
  END IF

WeitereDIRs:
  IF DIRCount(Ebene)<DIRNr(Ebene)THEN
   INCR DIRCount(Ebene)
   INCR Ebene
  ELSE
   WHILE Ebene
    DIRNr(Ebene)=0
    DIRCount(Ebene)=0
    DECR Ebene
    IF Ebene THEN IF DIRCount(Ebene)<DIRNr(Ebene)THEN WeitereDIRs
   WEND
  END IF
 WEND
 IF ASkins=0 THEN PRINT "Fehler_SkinlisteKeine"
 IF ASkins>1 THEN
  REM Sortiere Skinliste
  FOR x=1 TO ASkins-1
   t$=Skin$(x,0):z=x
   FOR y=x+1 TO ASkins
    IF Skin$(y,0)<t$ THEN t$=Skin$(y,0):z=y
   NEXT
   SWAP Skin$(x,0),Skin$(z,0)
   SWAP Skin$(x,1),Skin$(z,1)
  NEXT
 END IF
 
FreeVec FIBlock&


Dies ist ein veränderter Code aus Sudoku, der das Daten-Verzeichniss durchsucht. Leider verursacht diese Routine ein instabiles System.

Ich hab mir mal die AutoDocs durchgenommen und dort steht, das man FiBlock mit AllocDosObject() generieren soll?!?

Info:
Der Programm oben wurde verändert(mit Prints versehn, etc.).

Die Masterfrage:
Wo issen da der Fehler?
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

27.01.2008, 22:54 Uhr

Kaesebroetchen
Posts: 643
Nutzer
@Ralf27:
Steht bei AROS (was ja mehr oder weniger OS3.1 entspricht) auch so drin:

examine

AllocDosObject
C code:
/* Tags for AllocDosObject(). */

#define ADO_Dummy	(TAG_USER + 2000)

/* Tags for DOS_FILEHANDLE only. */
  /* Sets up the filehandle for the specified mode. Definitions are in
     <dos/dos.h> */
#define ADO_FH_Mode	(ADO_Dummy + 1) /* Sets up FH to the specified mode. */

/* Tags for DOS_CLI. If you do not specify these, dos will use reasonable
   default values. All these tags specify the buffer length for certain
   strings. */
  /* Length of current directory buffer. */
#define ADO_DirLen	(ADO_Dummy + 2)
  /* Length of command name buffer. */
#define ADO_CommNameLen (ADO_Dummy + 3)
  /* Length of command file buffer. */
#define ADO_CommFileLen (ADO_Dummy + 4)
  /* Length of buffer for CLI prompt. */
#define ADO_PromptLen	(ADO_Dummy + 5)

#endif /* DOS_DOSTAGS_H */


Ich weiß nicht ob dir das weiterhilft.
Auf jeden Fall findet man auf der AROS Seite und vor allem in den Quellcodes (contrib_source) oft die entscheidenden Informationen.

P.s. Warum steigst du eigentlich nicht auf C um ? Dann könntest du dein Programm für alle Amiga-artigen System kompilieren.
--
http://amidevcpp.amiga-world.de/

[ - Antworten - Zitieren - Direktlink - ]

27.01.2008, 23:03 Uhr

Ralf27
Posts: 2779
Nutzer
Zitat:
Original von Kaesebroetchen:
P.s. Warum steigst du eigentlich nicht auf C um ? Dann könntest du dein Programm für alle Amiga-artigen System kompilieren.

Zja, irgendwie sollte ich das schon machen. Aber ich schaff denn Absprung nicht. Ich schaff es einfach nicht...

Ok, also mit AllocDosObject()... hm, ist schon echt seltsam. Kurz mal die bescheidene Frage: Es muß also eine Adresse sein, die nicht nur gerade ist, sondern auch durch 4 teilbar? Jedenfalls hab ich das so verstanden. Mal sehn, wie ich das mit AllocDosObject() mach.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

27.01.2008, 23:30 Uhr

akl
Posts: 265
Nutzer
@Ralf27:
Adressen, die AllocVec() liefert, sind auch immer durch vier teilbar. Das Problem mit der Teilbarkeit stellt sich nur, wenn die C-Struktur "FileInfoBlock" auf dem Stack oder als Teil einer anderen C-Struktur angelegt wird.

[ - Antworten - Zitieren - Direktlink - ]

27.01.2008, 23:40 Uhr

Ralf27
Posts: 2779
Nutzer
Wie ich eben gesehn habe, hat sich wohl da seit OS1.2 "etwas" getan. :)

ExAll ist da wohl besser.
Da muß wohl noch einiges an dem Code poliert werden. Aber erst mal verstehn was da in denn Docs steht, da hab ich leider so meine Probleme.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

27.01.2008, 23:48 Uhr

Kaesebroetchen
Posts: 643
Nutzer
@Ralf27:
C code:
#include <stdio.h>
#include <stdlib.h>

#include <proto/dos.h>

int main(int argc, char *argv[])
{
  BPTR Extras;
  APTR FIB1;

  Extras = Lock("sys:extras",SHARED_LOCK );

  FIB1 = AllocDosObject(DOS_FIB, TAG_DONE );
  Examine(Extras, FIB1 );
  FreeDosObject(DOS_FIB,FIB1);

  system("PAUSE");
  return 0;
}


Hier mal ein Beispielprogramm für Examine.
Ich denke mal dass das unter os3.x noch genauso funktioniert ?



--
http://amidevcpp.amiga-world.de/

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 20:14 Uhr

Ralf27
Posts: 2779
Nutzer
@Kaesebroetchen:

hm, wie extrahiere ich die Daten? bzw. einfach nur statt AllocVec nur AllocDosObject benutzen?
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 20:59 Uhr

Ralf27
Posts: 2779
Nutzer
Ich hab es eben soweit umgebaut.Also jetzt einfach denn Speicher via AllocDosObject() geholt und mit FreeDosObject wieder freigegeben. Dazu noch Lock() jetzt mit SHARED_LOCK statt ACCESS_READ.

Ich hoffe das stimmt so...
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 21:07 Uhr

Kaesebroetchen
Posts: 643
Nutzer
Zitat:
Original von Ralf27:
@Kaesebroetchen:

hm, wie extrahiere ich die Daten?
--


FileInfoBlock ist eine Struktur.
C code:
/* Structure used to describe a directory entry. Note that not all fields
   are supported by all filesystems. This structure should be allocated
   with AllocDosObject(). */
struct FileInfoBlock
{
    LONG	     fib_DiskKey;
      /* See <dos/dosextens.h> for definitions. Generally: if this is >= 0
         the file described is a directory, otherwise it is a plain file. */
    LONG	     fib_DirEntryType;
      /* The filename (null-terminated). */
    UBYTE	     fib_FileName[MAXFILENAMELENGTH];
    LONG	     fib_Protection;   /* The protection bits (see below). */
    LONG	     fib_EntryType;
    LONG	     fib_Size;         /* The size of the file. */
    LONG	     fib_NumBlocks;    /* Number of blocks used for file. */
    struct DateStamp fib_Date;         /* Date of last change to file. */
    UBYTE	     fib_Comment[MAXCOMMENTLENGTH];  /* The filecomment (null-terminated). */
    UWORD	     fib_OwnerUID;     /* UserID of fileowner. */
    UWORD	     fib_OwnerGID;     /* GroupID of fileowner. */
    UBYTE	     fib_Reserved[32]; /* PRIVATE */
};


in C könntest du mit z.B.

deineVariable = FIB1.fib_Size;


Auf die einzelnen Elemente zugreifen.
Was für Klimmzüge du dafür in Basic machen musst kann ich dir leider nicht sagen.

--
http://amidevcpp.amiga-world.de/

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 21:09 Uhr

Ralf27
Posts: 2779
Nutzer
@Kaesebroetchen:

Oben steht ja das Programm. Ich hab die Änderung schon vorgenommen und es läuft. Die Frage ist nur, ob ich das richtig gemacht habe.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 21:31 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Kann Maxon Basic keine Rekursion?

Ich würde das ganze rekursiv implementieren, dann wird der Code viel kürzer und übersichtlicher und leichter zu debuggen. Dem Ebenen-rauf und runterzaehlen kann man sich schnell mal verhauen.

Ansonsten: ein einfaches Allocmem oder Allocvec sollte es tun. Ich kann mich erinnern, dass der Speicherbereich korrekt aligned sein muss, das ist wohl die einzige bedingung. Wenn du AllocDosObject nimmst, sollte das garantiert sein.


--
Thilo Köhler, Author von:
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, TK AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 21:34 Uhr

Ralf27
Posts: 2779
Nutzer
@Der_Wanderer:

Also, die Routine geht schon. Das Problem ist nur, das ich nicht wußte das ich jetzt AllocDosObject nehmen soll. Die Grundroutine hab ich aus einem OS1.2-Buch. Und dann war es eben so, das ich mit AllocMem bzw. AlloVec einiges im System durcheinander gebracht habe.
Denn in den AutoDoces steht, das man nur mit AllocDosObject denn FIBlock anfordern soll.

Wie meinst du das mit anderst Rekrusiv programmieren? Wie würde das aussehen?
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 21:53 Uhr

Der_Wanderer
Posts: 1229
Nutzer
> Wie meinst du das mit anderst Rekrusiv programmieren? Wie würde das aussehen?
Du hast mich falsch zitiert. Ich meinte nicht "anderst", sondern rekursiv.
Was du implementiert hast ist keine Rekursion, eher Pseudo-Rekusion. Eigentlich ist es aber imperativ implementiert.

Rekusiv würde so aussehen (Pseudo Code)
Dadruch sparst du dir das ganze Geraffel mit den "Ebenen".

code:
ScanDir(path) {
  While ExNext(path) {
    If IsDir?
      ScanDir(path+dir) <= das ist eine Rekursion
    Else
      File found!
  }
}

ScanDir("Root:") <= starte z.B. bei "Root:"


"Rekursion" ist das, wo im Informatik Unterricht in der Schule die Mädchen aussteigen. :lach:

Oder da fällt mir der noch ein:
"Um Rekursion zu verstehen, muss man zunächst einmal die Rekursion verstehen."
--
Thilo Köhler, Author von:
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, TK AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 28.01.2008 um 22:05 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

28.01.2008, 22:05 Uhr

Ralf27
Posts: 2779
Nutzer
@Der_Wanderer:

Ah, jetzt, versteh. Das geht auch in MaxonBasic, aber ich hab das noch nie eingesetzt.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

29.01.2008, 02:56 Uhr

Andreas_Wolf
Posts: 2980
Nutzer
> imperativ

Ich glaube, du meinst "iterativ" :-)

[ - Antworten - Zitieren - Direktlink - ]

29.01.2008, 04:53 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Andreas_Wolf:
> imperativ

Ich glaube, du meinst "iterativ" :-)


Nein, er meint "prozedurale Iteration" ;) Iterieren kann man sowohl rekursiv als auch nicht-rekursiv (imperativ ist da wohl nicht ganz der richtige Begriff), wobei letzteres Stack- und Debugging-freundlicher ist, Rekursion hingegen vor allem "eleganteren" Sourcecode ergibt (weil kürzer und, sofern man verstanden hat, daß man, um Rekursion zu verstehen, Rekursion verstehen muß, auch leichter lesbar :D )

Ich denke aber, daß es einstweilen sinnvoller ist, erst einmal den eigentlichen Fehler in Ralfs Vorgehensweise zu finden und zu beheben, bevor er den Code komplett umstrickt und mit Rekursion evtl. noch mehr Fehler einbaut.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

29.01.2008, 12:18 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Ihr habt ja recht. Grundlagen sind schon eine Weile her.
--
Thilo Köhler, Author von:
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, TK AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

30.01.2008, 20:32 Uhr

Ralf27
Posts: 2779
Nutzer
Zja, die Verzeichnissdurchsuchung bekomme ich wohl ohne Bugs nicht hin... hm. :( Jedenfalls produziert wohl als noch ein instabiles System. MuForce zeigt nichts an, aber ich sehs am Menu(!) an, das es einiges im System verhaut...
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

30.01.2008, 21:06 Uhr

Ralf27
Posts: 2779
Nutzer
Was ich gerade habe sieht so aus:

code:
ListeSkins:
 ASkins=0
 FIBlock&=AllocDosObject&(DOS_FIB&,TAG_DONE&)
 IF FIBlock&=0 THEN
  Var$=STR$(FileInfoBlock_sizeof%)
  LocMeldung Fehler_SkinlistSpeicher
  RETURN
 END IF
 DIR$(0,0)="Daten"
 DIRCount(0)=0
 DIRNr(0)=0
 Ebene=1
 WHILE Ebene
  v$=""
  FOR x=0 TO Ebene-1
   v$=v$+DIR$(DIRCount(x),x)
   IF x<Ebene-1 THEN v$=v$+"/"
  NEXT
  FileLock&=Lock&(SADD(v$+CHR$(0)),SHARED_LOCK&)
  IF FileLock&=0 THEN
   Var$=STR$(IOErr$)
   LocMeldung Fehler_SkinlisteLaden
   Ebene=0
  ELSE
   Status=Examine(FileLock&,FIBlock&)
   WHILE Status
    Status=ExNext(FileLock&,FIBlock&)
    IF Status THEN
     FileName$=PEEK$(FIBlock&+fib_FileName%)
     IF PEEKL(FIBlock&+fib_DirEntryType%)>0 THEN
      INCR DIRNr(Ebene)
      DIR$(DIRNr(Ebene),Ebene)=FileName$
     ELSE
      IF RIGHT$(FileName$,4)=".dat" THEN
       OeffneDat v$+"/"+FileName$
       Dat a
       IF a$=="SUDOKU_V1.4"THEN
        Dat a
       ELSE
        IF InstrDat("Spielart")THEN Dat a
       END IF
       IF a=Opt(34) AND ASkins<MaxSkins THEN
        INCR ASkins
        Skin$(ASkins,0)=MID$(FileName$,1,LEN(FileName$)-4)
        Skin$(ASKins,1)=v$+"/"
       END IF
      END IF
     END IF
    END IF
   WEND
   UnLock FileLock&
  END IF

WeitereDIRs:
  IF DIRCount(Ebene)<DIRNr(Ebene)THEN
   INCR DIRCount(Ebene)
   INCR Ebene
  ELSE
   WHILE Ebene
    DIRNr(Ebene)=0
    DIRCount(Ebene)=0
    DECR Ebene
    IF Ebene THEN IF DIRCount(Ebene)<DIRNr(Ebene)THEN WeitereDIRs
   WEND
  END IF
 WEND
 FreeDosObject DOS_FIB&,FIBlock&
 ...

Das produziert aber als noch einen Fehler, bzw. macht das System instabil. Ohne dieses Unterprogramm läuft WBSudoku ohne Fehler.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

31.01.2008, 03:46 Uhr

whose
Posts: 2156
Nutzer
@Ralf27:

Bist Du Dir sicher, daß der Fehler nur aus dem Abschnitt kommt? Soweit ich das überblicken kann, sieht das Ganze soweit ok aus und dürfte auch nicht im Speicher "rumsauen" (Du schriebst ja, daß damit wohl Menüpunkte durcheinandergewürfelt werden, was eigentlich nur bei einem Speicherleck passieren kann).

OeffneDat() und InstrDat() sind sauber? Hast Du die beiden mal näher untersucht? Gerade bei Laderoutinen lauert gern mal der "Kollege Null-Zeiger", das solltest Du also ausschließen können, bevor wir in dem obigen Teil weiterschauen. Ich kann da nämlich so ohne weiteres nichts dramatisches entdecken... :(

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Antworten - Zitieren - Direktlink - ]

31.01.2008, 07:40 Uhr

Ralf27
Posts: 2779
Nutzer
Im folgenden sind die Routinen. Ich kann da keinen Fehler finden.
Bei LeseDateiAlsString benutze ich einen eigenen FIBlock.

code:
FUNCTION InstrDat(a$)
 SHARED Dat$,DatP
 STATIC a
 a=INSTR(UCASE$(Dat$),UCASE$(a$)+"=")
 IF a THEN DatP=a+LEN(a$)
 InstrDat=a
END FUNCTION

SUB OeffneDat(FileName$)
 SHARED Dat$,DatP
 STATIC a$,t$,l,x
 LeseDateiAlsString FileName$,a$
 a$=a$+","+CHR$(10):DatP=0
 Dat$="":l=LEN(a$)
 REM Kommentar loeschen
 FOR x=1 TO l
  t$=MID$(a$,x,1)
  IF t$<>";"THEN
   Dat$=Dat$+t$
  ELSE
   x=INSTR(x,a$,CHR$(10))-1
  END IF
 NEXT
END SUB

SUB LeseDateiAlsString(FileName$,a$)
 SHARED Fehler,Var$
 STATIC FIBlock&,h&,l&,junk&
 a$=""
 FIBlock&=AllocDosObject&(DOS_FIB&,TAG_END&)
 IF FIBlock& THEN
  h&=xOpen&(SADD(FileName$+CHR$(0)),MODE_OLDFILE&)
  IF h& THEN
   IF ExamineFH&(h&,FIBlock&)THEN
    l&=PEEKL(FIBlock&+fib_Size%)
    a$=SPACE$(l&)
    IF l&<>xRead&(h&,SADD(a$),l&)THEN Fehler=Fehler_DateiFertiglesen
   ELSE
    Fehler=Fehler_DateiVerarbeiten
   END IF
   junk&=xClose&(h&)
  ELSE
   Fehler=Fehler_DateiOeffnen
  END IF
  FreeDosObject DOS_FIB&,FIBlock&
 ELSE
  Var$=STR$(FileInfoBlock_sizeof%)
  LocMeldung Fehler_SkinlistSpeicher
 END IF
END SUB

--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

01.02.2008, 12:55 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Ralf27:
Im folgenden sind die Routinen. Ich kann da keinen Fehler finden.
Bei LeseDateiAlsString benutze ich einen eigenen FIBlock.

Warum eigentlich? Nach Examine/ExNext hast Du doch schon einen FileInfoBlock, aus dem Du die Dateilänge auslesen kannst. Warum übergibst Du sie nicht einfach der Leseroutine und sparst Dir ein weiteres Examine?

Wie auch immer, hier mal ein Stück Code als Gedankenanregung:
BASIC code:
REM $INCLUDE DOS.bh
LIBRARY OPEN "dos.library"

Action$="Scanning Skins"+CHR$(0)

numFoundFiles&=0
DIM foundFiles$(numFoundFiles&+10)

SUB Push(file$)
SHARED foundFiles$(),numFoundFiles&
LOCAL copy$, newCapacity&
  IF numFoundFiles&>=UBOUND(foundFiles$) THEN
    DIM copy$(numFoundFiles&)
    FOR i&=0 TO numFoundFiles&:copy$(i&)=foundFiles$(i&):NEXT
    newCapacity&=UBOUND(foundFiles$)*2
    REDIM foundFiles$(newCapacity&)
    FOR i&=0 TO numFoundFiles&:foundFiles$(i&)=copy$(i&):NEXT
    ERASE copy$
  END IF
  foundFiles$(numFoundFiles&)=file$
  INCR numFoundFiles&
END SUB

FUNCTION SubLock&(ParentLock&, fileName&)
LOCAL old&
  old&=CurrentDir&(ParentLock&)
  SubLock&=Lock&(fileName&, SHARED_LOCK&)
  dummy&=CurrentDir&(old&)
END FUNCTION

FUNCTION scan&(DirLock&,dirName$)
LOCAL fib&,status&,subDir&,code&,fileName$
  fib&=AllocDosObject&(DOS_FIB&,TAG_DONE&)
  IF fib&=0 THEN scan&=ERROR_NO_FREE_STORE&:EXIT FUNCTION
  status&=Examine(DirLock&,fib&)
  IF status& = 0 THEN HandleError
  status&=ExNext(DirLock&,fib&)
  WHILE status&
    fileName$=PEEK$(fib&+fib_FileName%)
    type&=PEEKL(fib&+fib_DirEntryType%)
    IF type&>=0 AND type&<>ST_SOFTLINK& THEN
      subDir&=SubLock&(DirLock&, fib&+fib_FileName%)
      IF subDir&=0 THEN HandleError
      subStatus&=scan&(subDir&, dirName$+fileName$+"/")
      UnLock subDir&
      IF subStatus& THEN scan&=subStatus&: GOTO ResultSet
    ELSE
      IF UCASE$(RIGHT$(fileName$,4))=".DAT" THEN Push(dirName$+fileName$)
    END IF
    status&=ExNext(DirLock&,fib&)
  WEND
  code&=IoErr&()
  IF code&=ERROR_NO_MORE_ENTRIES& THEN scan&=0 ELSE scan&=code&
  FreeDosObject DOS_FIB&,fib&
  EXIT FUNCTION
HandleError:
  scan&=IoErr&()
ResultSet:
  FreeDosObject DOS_FIB&,fib&
END FUNCTION

dir&=CurrentDir&(0&)
Code&=Scan&(dir&, "")
x&=CurrentDir&(dir&)

IF Code& THEN
  Reason$=SPACE$(LEN(Action$)+81)
  msgLen&=Fault&(Code&, SADD(Action$), SADD(Reason$), LEN(Reason$))
  Reason$=LEFT$(Reason$, msgLen&)
  PRINT Reason$
ELSE
  ? numFoundFiles&;" files"
  FOR f&=0 TO numFoundFiles&-1
    PRINT f&;foundFiles$(f&)
  NEXT f&
END IF

END


mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

01.02.2008, 21:52 Uhr

Ralf27
Posts: 2779
Nutzer
Zitat:
Original von Holger:
Zitat:
Original von Ralf27:
Im folgenden sind die Routinen. Ich kann da keinen Fehler finden.
Bei LeseDateiAlsString benutze ich einen eigenen FIBlock.

Warum eigentlich? Nach Examine/ExNext hast Du doch schon einen FileInfoBlock, aus dem Du die Dateilänge auslesen kannst. Warum übergibst Du sie nicht einfach der Leseroutine und sparst Dir ein weiteres Examine?
Das stimmt schon. Ich rufe diese Unterroutine aber nicht nur aus dem Dirscan auf, sondern auch aus anderen Teilen des Programms.

Ich hoffe das das nicht den Fehler verursacht, bzw. das das so legal ist.
Zitat:
Wie auch immer, hier mal ein Stück Code als Gedankenanregung:
Wow, das muß ich mir erst mal genauer ansehn um zu sehn wie es funktioniert. Danke.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

24.09.2008, 23:15 Uhr

inq
Posts: 445
Nutzer
@Ralf27:
hoi.
das wird der fehler sein. examine_ schiebt die FIB daten immer in den selben vorher allozierten memblock; nach exnext_ sind die daten anders. wenn du den FIB behalten willst, musst du die entspr. daten zwischenspeichern. übrigens sollte man speicher für dos-anw prinzipiell mit MEMF_CLEAR allozieren-kann einigen ärger sparen :-)

[ - Antworten - Zitieren - Direktlink - ]

25.09.2008, 09:11 Uhr

Ralf27
Posts: 2779
Nutzer
Zitat:
Original von inq:
@Ralf27:
hoi.
das wird der fehler sein. examine_ schiebt die FIB daten immer in den selben vorher allozierten memblock; nach exnext_ sind die daten anders. wenn du den FIB behalten willst, musst du die entspr. daten zwischenspeichern. übrigens sollte man speicher für dos-anw prinzipiell mit MEMF_CLEAR allozieren-kann einigen ärger sparen :-)


Das mit MEMF_CLEAR sollte ich wirklich mal einbauen, aber mit dem FIBlock...

(dos.doc)
code:
So, follow these steps to examine a directory:
 1) Pass a Lock and a FileInfoBlock to Examine().  The lock must
    be on the directory you wish to examine.
 2) Pass ExNext() the same lock and FileInfoBlock.
 3) Do something with the information returned in the FileInfoBlock.
    Note that the fib_DirEntryType field is positive for directories,
    negative for files.
 4) Keep calling ExNext() until it returns FALSE.  Check IoErr()
    to ensure that the reason for failure was ERROR_NO_MORE_ENTRIES.


Ich bin wirklich nicht gut in Englisch, aber Punkt 2 liest sich so, das der FIBlock von Examine() und ExNext() die gleichen sein müssen, bzw. ich erst dann an die Daten gehn sollte.
--
http://www.alternativercomputerclub.de.vu

[ - Antworten - Zitieren - Direktlink - ]

25.09.2008, 09:38 Uhr

Der_Wanderer
Posts: 1229
Nutzer
So mache ich das in Amiblitz3, und das funktioniert:
code:
Function.l scan {path.s}
DEFTYPE.FileInfoBlock fib
lock.l = Lock_(&path.s,#ACCESS_READ)
If lock
  If Examine_ (lock,&fib)
    While ExNext_(lock,&fib)
      filename.s = path.s+"/"+Peek.s(&fibfib_FileName)
      If fibfib_DirEntryType<0
        ; Datei!
      Else
        ; Verzeichnis!
        scan{filename.s}
      End If
    Wend
  End If
  UnLock_ lock
End If
End Function

scan{"DH0:ScanFromHere"}


P.S. das konkatenieren des Pfades mit dem Dateinamen habe ich mal mit "+" geschrieben, um keine unnötigen Amiblitz Befehle mit reinzubringen. Eigentlich sollte man AddPart aus der dos.library benutzen.
Um zukunftssicher zu ein, kannst du den DEFTPYE.FileInfoBlock mit
code:
*fib.FileInfoBlock = AllocDosObject_ (#DOS_FIB,#TAG_DONE)
...
FreeDosObject_ #DOS_FIB,*fib


ersetzen. Die Dateigröße steht in fibfib_Size.
BTW, wie ist das bei Dateien >=4GB gelöst (vorrausgesetzt, das Filesystem unterstützt das)?


--
Thilo Köhler, Author von:
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, TK AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von Der_Wanderer am 25.09.2008 um 09:40 Uhr geändert. ]

[ Dieser Beitrag wurde von Der_Wanderer am 25.09.2008 um 09:43 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

27.09.2008, 14:38 Uhr

Wishmaster
Posts: 140
Nutzer
Rekursive Verzeichnishandhabung ist elegenat und kompakt.
Nur muss Mann dabei den Stapelspeicher im Auge behalten, damit der nicht überläuft.
Vorteilhaft ist dabei, wenn der Compiler Stackchecking unterstützt.
--
Pegasos MorphOS

[ - Antworten - Zitieren - Direktlink - ]

29.11.2009, 22:06 Uhr

inq
Posts: 445
Nutzer
Zitat:
Original von Der_Wanderer:
So mache ich das in Amiblitz3, und das funktioniert:
code:
Function.l scan {path.s}
DEFTYPE.FileInfoBlock fib
lock.l = Lock_(&path.s,#ACCESS_READ)
If lock
  If Examine_ (lock,&fib)
    While ExNext_(lock,&fib)
      filename.s = path.s+"/"+Peek.s(&fibfib_FileName)
...
End Function

scan{"DH0:ScanFromHere"}


hoi.
(besserwissermodus)
entschuldige bitte, dass ich das o.g. gerade erst bemerke, aber hast du für den fall <path.s="DH0:"> auch noch das gefühl, es würde funktionieren? ?(
(/besserwissermodus)
gruss
inq

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > Rekrusives durchsuchen von Verzeichnissen [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.