Win3x.Org

Windows & DOS Community

[Résolu] Incapacité d'afficher des fichiers

Post Reply   Page 1 of 1  [ 10 posts ]
Author Message
victornement
Post subject: [Résolu] Incapacité d'afficher des fichiers
Posted: 21 April, 14:07
Membre inscrit
User avatar
Offline
 
Posts: 317
Joined: 20 January, 12:23
 
Bonjours,
j'ai réçemment essayé de mettre au point un programme en Quick Basic pour afficher le contenu d'un dossier.
QB dispose déjà d'une fonction préintégré nommée files qui écrit sur l'écran le contenu du répertoire en cours.
Mais je recherche des sources qui s'utilisent à la maniére de FindFirstFile et de FindNextFile.
J'ai longtemp cherché à utiliser les fonction 4E et 4F de l'interruption 21h sans succés, pourtant je ne sais toujours pas ou était mon erreur.
Dans mon code je commençais par appeler la fonction 4E, puis obtenir l'adresse de la DTA, puis reguarder dans la DTA... sans rien y trouver :cry:
J'ai trouvé sur MSDN une source en Quick Basic 2. La voici :
DIM InArray%(9), OutArray%(9)
AX% = 0: DX% = 3: DS% = 8: CX% = 2  ' -- Register locations
DTA$ = SPACE$(43)                   ' -- DTA Buffer size
Path$ = "*.*" + CHR$(0)             ' -- Search path, plus null byte

REM -- Find Segment and Offset for the DTA (Disk Transfer Area)
CALL PTR86(Seg1%, Off1%, VARPTR(DTA$))

REM -- The real Offset for the string DTA$ is found by using the
REM    SADD function.
Off1% = SADD(DTA$)

REM -- Set the DTA with Interrupt Hex 21, and Function Hex 1A
InArray%(AX%) = &H1A00
InArray%(DX%) = Off1%
InArray%(DS%) = Seg1%
CALL INT86(&H21, VARPTR(InArray%(0)), VARPTR(OutArray%(0)))

REM -- Find the Segment and Offset for the Search Path
CALL PTR86(Seg1%, Off1%, VARPTR(Path$))

REM -- Real Offset is found by using the SADD function
Off1% = SADD(Path$)

REM -- Find the first file with Interrupt Hex 21, Function Hex 4E
InArray%(AX%) = &H4E00
InArray%(CX%) = 22
InArray%(DX%) = Off1%
InArray%(DS%) = Seg1%
CALL INT86(&H21, VARPTR(InArray%(0)), VARPTR(OutArray%(0)))

REM -- Stay in while loop until
REM    18 = No more files
REM     3 = Invalid search path -OR- no files found
WHILE (OutArray%(AX%) <> 18) AND (OutArray%(AX%) <> 3)
   a% = CVI(MID$(DTA$, 27, 2))  ' -- Low word of file size
   b% = CVI(MID$(DTA$, 29, 2))  ' -- High word of file size
   IF a% < 0 THEN               ' -- Calculate size relative to
      d! = 65536 + a%           '    Low word
   ELSE
      d! = a%
   END IF
   IF b% < 0 THEN               ' -- Calculate size with High word
      d! = d! + (65536 * (65536 + b%))
   ELSE
      d! = d! + (65536 * b%)
   END IF
   PRINT RIGHT$(DTA$, 13);      ' -- Print file name
   PRINT "  ";
   PRINT d!                     '    and file size
   MID$(DTA$, 31, 13) = SPACE$(13) ' -- Blank out current name
   InArray%(AX%) = &H4F00       ' Function Hex 4F - Find Next File
   CALL INT86(&H21, VARPTR(InArray%(0)), VARPTR(OutArray%(0)))
WEND
END
Seulement, je souhaiterai l'utiliser en Quick Basic 4.5, alors j'ai essayer de la convertir, toujours sans succés et toujours sans comprendre mon erreur. Je me suis arrêté avant d'entrer dans la boucle, car il était inutile d'aller plus loin, en éffet, la chaine DTA ne contient rien.
TYPE RegTypex
   AX    AS INTEGER
   BX    AS INTEGER
   CX    AS INTEGER
   DX    AS INTEGER
   BP    AS INTEGER
   SI    AS INTEGER
   DI    AS INTEGER
   DS    AS INTEGER
   ES    AS INTEGER
   Flags AS INTEGER
END TYPE
DIM DTA AS STRING
DTA = SPACE$(43)
DIM Path AS STRING
Path = "*.*" + CHR$(0)
DIM Segment AS INTEGER, Offset AS INTEGER
Segment = VARSEG(DTA)
Offset = SADD(DTA)
DIM RegIn AS RegTypex, RegOut AS RegTypex
RegIn.AX = &H1A00
RegIn.DX = Offset
RegIn.DS = Segment
CALL Interruptx(&H21, RegIn, RegOut)

Segment = VARSEG(Path)
Offset = SADD(Path)
DIM RegIn2 AS RegTypex, RegOut2 AS RegTypex
RegIn.AX = &H4E00
RegIn.CX = 23
RegIn.DX = Offset
RegIn.DS = Segment
CALL Interruptx(&H21, RegIn2, RegOut2)
Alors comment lire le contenu d'un répertoire en Quick Basic ? Quelle erreur y a-t'il dans mon code ?
J'ai testé toute sorte de code différents sans réussir ce que je souhaite :evil:

Last edited by victornement on 13 August, 17:26, edited 2 times in total.

_________________

Salut


Top
Quote
flo3x
Post subject:
Posted: 21 April, 18:29
 
 
Je ne suis pas sûr, mais tu peux peut-être utiliser un truc du genre : (le code n'est pas bon car je ne sais pas vraiment la commande)
SHELL "dir c:\repertoire > c:\file.txt"
OPEN "c:\file.txt" for output as #1
'tu sélectionne la première ligne ou la dernière suivant ce que tu veux...
'après la commande, je la connaissais mais ça fait longtemps que je n'ai pas fait de QBasic...
CLOSE #1
En tout cas le code c'est un truc du genre ...
Voila, j'espère que j'ai répondu à la bonne question :D car je ne les comprends pas très souvent... :oops:


Top
Quote
victornement
Post subject:
Posted: 21 April, 19:31
Membre inscrit
User avatar
Offline
 
Posts: 317
Joined: 20 January, 12:23
 
Pour ceux qui ne suivent pas, ton code consiste à éxécuter la commande dir redirigée dans un fichier, puis d'ouvrir ce fichier.
Mais je n'utilise pas cette méthode car c'est facile à faire et ce n'est pas propre du tout :wink:.
Moi je souhaite simplement réussir à utiliser la fonction 4E de l'interruption 21h. Mais merci quand même.

_________________

Salut


Top
Quote
corwintirnanog
Post subject:
Posted: 21 April, 19:53
Membre inscrit
User avatar
Offline
 
Posts: 326
Joined: 23 October, 14:13
 
Je n'ai pas beaucoup de temps et je ne connais pas QB, mais il me semble que tu réserve une zone nommée DTA or la DTA est une zone de l'OS, ce n'est pas une zone que tu dois réserver. Je pense que ça explique ton problème.


Top
Quote
michel
Post subject:
Posted: 21 April, 20:02
Administrateur
User avatar
Offline
 
Posts: 2632
Joined: 07 February, 19:46
Retro PC: IBM - PS2 Modèle 85 (carte mère en panne)
 
Tiens une source
'$INCLUDE: 'qb.bi'
DECLARE SUB suivant ()
DECLARE SUB dta ()
DECLARE SUB premier (fic$)
'
' Ce programme affiche les fichiers présents sur une unité
' courante, programme simplifié sans gestion des répertoires...
'

SCREEN 0: CLS
' Definir le Masque Fichier
MASQ$ = "*.*" + CHR$(0)
CALL dta
CALL premier(MASQ$)
NBR% = 0
DO
	IF trouve THEN
		NBR% = NBR% + 1: NOMFIC$ = ""
		DEF SEG = dtaseg
		FOR I = 30 TO 42
			S% = PEEK(dtaofs + I)
			IF S% = 0 THEN EXIT FOR
			NOMFIC$ = NOMFIC$ + CHR$(S%)
		NEXT I
		DEF SEG
		PRINT NOMFIC$
	ELSE
		DEF SEG
		EXIT DO
	END IF
	CALL suivant
LOOP
PRINT STRING$(60, 196)
PRINT "FIN DE PROGRAMME, Nombre De Fichiers : "; NBR%
END

SUB dta STATIC
SHARED dtaofs, dtaseg, inregx AS RegTypeX, outregx AS RegTypeX
	inregx.ax = &H2F00
	CALL INTERRUPTX(&H21, inregx, outregx)
	dtaofs = outregx.bx
	dtaseg = outregx.es
END SUB

SUB premier (fic$) STATIC
SHARED trouve, inreg AS RegType, outreg AS RegType
	inreg.ax = &H4E00
	inreg.cx = &HFF
	inreg.dx = SADD(fic$)
	CALL INTERRUPT(&H21, inreg, outreg)
	trouve = ((outreg.flags AND 1) = 0)
END SUB

SUB suivant STATIC
SHARED inreg AS RegType, outreg AS RegType, trouve
	inreg.ax = &H4F00
	CALL INTERRUPT(&H21, inreg, outreg)
	trouve = ((outreg.flags AND 1) = 0)
END SUB
Je m'en sers et ça marche.

Last edited by michel on 21 April, 20:04, edited 1 time in total.

_________________



Top
Quote
victornement
Post subject:
Posted: 21 April, 20:03
Membre inscrit
User avatar
Offline
 
Posts: 317
Joined: 20 January, 12:23
 
corwintirnanog wrote:
Je n'ai pas beaucoup de temps et je ne connais pas QB, mais il me semble que tu réserve une zone nommée DTA or la DTA est une zone de l'OS, ce n'est pas une zone que tu dois réserver. Je pense que ça explique ton problème.
Tu es sûr ? Sur tout les sites que j'ai trouvé, il semble qu'elle est toujours située dans le psp, même qu'elle ce situe à l'offset 170 (décimal) par défaut.
D'ailleurs, dans le code de Microsoft, il y a un commentaire en Anglais qui dit clairement "Set the DTA" où quelque chose comme sa.
Il y a même deux fonctions pour obtenir où spécifier la position de la DTA.
En tout cas je me suis servi de ces documentations :
http://www.gladir.com/LEXIQUE/INTR/int2 ... Target=ASM (spécifier ou se situe la DTA)
http://www.gladir.com/LEXIQUE/INTR/int2 ... Target=ASM (obtenir l'adresse de la DTA)
http://www.gladir.com/LEXIQUE/INTR/int2 ... Target=ASM (obtenir le 1er fichier)
http://www.gladir.com/LEXIQUE/INTR/int2 ... Target=ASM (obtenir le fichier suivant)


----
Publié : Lundi 21 Avril 2008 19:05:09
michel wrote:
Tiens une source
  SPOILER Disabled
'$INCLUDE: 'qb.bi'
DECLARE SUB suivant ()
DECLARE SUB dta ()
DECLARE SUB premier (fic$)
'
' PROGRAMME ** DIRSIMP.BAS ** Affiche les fichiers présents
' sur unité courante, Programme simplifié sans gestion des
' répertoires ...
'
SCREEN 0: CLS
' Definir le Masque Fichier
MASQ$ = "*.*" + CHR$(0)
CALL dta
CALL premier(MASQ$)
NBR% = 0
DO
	IF trouve THEN
		NBR% = NBR% + 1: NOMFIC$ = ""
		DEF SEG = dtaseg
		FOR I = 30 TO 42
			S% = PEEK(dtaofs + I)
			IF S% = 0 THEN EXIT FOR
			NOMFIC$ = NOMFIC$ + CHR$(S%)
		NEXT I
		DEF SEG
		PRINT NOMFIC$
	ELSE
		DEF SEG
		EXIT DO
	END IF
	CALL suivant
LOOP
PRINT STRING$(60, 196)
PRINT "FIN DE PROGRAMME, Nombre De Fichiers : "; NBR%
END

SUB dta STATIC
SHARED dtaofs, dtaseg, inregx AS RegTypeX, outregx AS RegTypeX
	inregx.ax = &H2F00
	CALL INTERRUPTX(&H21, inregx, outregx)
	dtaofs = outregx.bx
	dtaseg = outregx.es
END SUB

SUB premier (fic$) STATIC
SHARED trouve, inreg AS RegType, outreg AS RegType
	inreg.ax = &H4E00
	inreg.cx = &HFF
	inreg.dx = SADD(fic$)
	CALL INTERRUPT(&H21, inreg, outreg)
	trouve = ((outreg.flags AND 1) = 0)
END SUB

SUB suivant STATIC
SHARED inreg AS RegType, outreg AS RegType, trouve
	inreg.ax = &H4F00
	CALL INTERRUPT(&H21, inreg, outreg)
	trouve = ((outreg.flags AND 1) = 0)
END SUB
Je m'en sers et ça marche.
Merci :D
Je vais pouvoir la personnaliser un peu et comprendre mon erreur !

_________________

Salut


Top
Quote
corwintirnanog
Post subject:
Posted: 21 April, 20:09
Membre inscrit
User avatar
Offline
 
Posts: 326
Joined: 23 October, 14:13
 
Michel est toujours impressionant de précision et de concision :-)

Sinon A+, mon épouse attends l'ordi et je ne pourrai pas le garder plus longtemps ;-)


Top
Quote
victornement
Post subject:
Posted: 21 April, 22:46
Membre inscrit
User avatar
Offline
 
Posts: 317
Joined: 20 January, 12:23
 
Je n'ai pas toujours compris mon erreur mais ce n'est pas grave :).
Au passage de l'edit du sujet (ajout de la chaine "[résolu]"), je poste ma version du code, qui est bien plus performante que celle d'en haut et qui n'a besoins que de deux fonction utilisables séparément :
DECLARE FUNCTION FindFirstFile$ (fic$)
DECLARE FUNCTION FindNextFile$ ()
TYPE RegTypex
   AX    AS INTEGER
   BX    AS INTEGER
   CX    AS INTEGER
   DX    AS INTEGER
   BP    AS INTEGER
   SI    AS INTEGER
   DI    AS INTEGER
   Flags AS INTEGER
   DS    AS INTEGER
   ES    AS INTEGER
END TYPE
CLS
DIM Recherche AS STRING
Recherche = FindFirstFile$("*.*")
WHILE Recherche <> CHR$(0)
PRINT Recherche
Recherche = FindNextFile$
WEND

FUNCTION FindFirstFile$ (File AS STRING)
DIM Fichier AS STRING
Fichier = File + CHR$(0)
DIM RegIn AS RegTypex, RegOut AS RegTypex
RegIn.AX = &H4E00
RegIn.CX = &HFF
RegIn.DX = SADD(Fichier)
CALL Interrupt(&H21, RegIn, RegOut)
IF RegOut.Flags = 2 THEN
   'Recherche de la position de la DTA
   RegIn.AX = &H2F00
   RegIn.CX = 0
   RegIn.DX = 0
   CALL INTERRUPTX(&H21, RegIn, RegOut)
   DIM DTASegment AS INTEGER, DTAOffset AS INTEGER
   DTASegment = RegOut.ES
   DTAOffset = RegOut.BX

   'Lecture du nom de fichier
   DEF SEG = DTASegment
   FOR A = 30 TO 42
      Char = PEEK(DTAOffset + A)
      IF Char = 0 THEN EXIT FOR
      TmpStr$ = TmpStr$ + CHR$(Char)
   NEXT
   DEF SEG
ELSE
   TmpStr$ = CHR$(0)
END IF
FindFirstFile$ = TmpStr$
END FUNCTION

FUNCTION FindNextFile$
DIM RegIn AS RegTypex, RegOut AS RegTypex
RegIn.AX = &H4F00
CALL Interrupt(&H21, RegIn, RegOut)
IF RegOut.Flags = 2 THEN
   'Recherche de la position de la DTA
   DIM DTASegment AS INTEGER, DTAOffset AS INTEGER
   RegIn.AX = &H2F00
   RegIn.CX = 0
   RegIn.DX = 0
   CALL INTERRUPTX(&H21, RegIn, RegOut)
   DTASegment = RegOut.ES
   DTAOffset = RegOut.BX
   
   'Lecture du nom de fichier
   DEF SEG = DTASegment
   FOR A = 30 TO 42
      Char = PEEK(DTAOffset + A)
      IF Char = 0 THEN EXIT FOR
      TmpStr$ = TmpStr$ + CHR$(Char)
   NEXT
   DEF SEG
ELSE
   TmpStr$ = CHR$(0)
END IF
FindNextFile$ = TmpStr$
END FUNCTION

_________________

Salut


Top
Quote
michel
Post subject:
Posted: 22 April, 00:20
Administrateur
User avatar
Offline
 
Posts: 2632
Joined: 07 February, 19:46
Retro PC: IBM - PS2 Modèle 85 (carte mère en panne)
 
flo3x wrote:
Je ne suis pas sûr, mais tu peux peut-être utiliser un truc du genre : (le code n'est pas bon car je ne sais pas vraiment la commande)
SHELL "dir c:\repertoire > c:\file.txt"
OPEN "c:\file.txt" for output as #1
'tu sélectionne la première ligne ou la dernière suivant ce que tu veux...
'après la commande, je la connaissais mais ça fait longtemps que je n'ai pas fait de QBasic...
CLOSE #1
En tout cas le code c'est un truc du genre ...
Voila, j'espère que j'ai répondu à la bonne question :D car je ne les comprends pas très souvent... :oops:
Trop compliqué ton truc et il manque une boucle DO.....LOOP UNTIL EOF(1) pour faire afficher toutes les lignes de file.txt.

Y'a plus simple et sans bouffer toute la mémoire avec le Shell :
FILES
En ajoutant une bonne gestion de l'erreur 53 (si le répertoire en cours est vide) :lol:

_________________



Top
Quote
flo3x
Post subject:
Posted: 22 April 2023 17:59
 
 
Ok merci de m'avoir corrigé ... Ça fait plaisir quand même quand je vois tout ce monde qui programme en QBasic (dont je connais les bases) et que dans leur code je ne connais pas grand chose comme commandes !!! :lol:
Et aussi, bonne journée ! :wink:


Top
Display: Sort by: Direction:
Post Reply   Page 1 of 1  [ 10 posts ]
Return to “Questions et problèmes résolus”
Jump to: