[Programmation] Navigation dans un système de fichier Fat
Répondre à la discussion
Affichage des résultats 1 à 4 sur 4

Navigation dans un système de fichier Fat



  1. #1
    scaypapa

    Navigation dans un système de fichier Fat


    ------

    Bonjour,

    J'avance...
    Maintenant que j'arrive à lire ma carte SD, je veux naviguer dedans avec la librairie FatFs.

    Encore une fois, ce message serait peut-être plus à sa place dans la section Programmation, n'hésitez pas à déplacer si besoin.

    Mon but serait d'avoir 4 boutons : fichier/dossier suivant, fichier/dossier précédent, ouvrir et fermer. Rien d'exceptionnel quoi, je ne pense pas être le premier à vouloir faire ça.
    Sauf que malgré des heures de recherche, je ne trouve pas de moyen "simple" d'implémenter la fonction "Précédent". Les éléments d'un dossiers sont lus dans l'ordre séquentiel et on ne peut pas revenir en arrière.
    Je suis très surpris de ne trouver aucune doc ou aucun tuto sur ce sujet dans les méandres du web...

    J'ai imaginé 2 solutions, qui fonctionnent très bien mais qui ne me semblent pas très "propres".
    J'aimerais avoir votre avis éclairé sur la meilleure méthode, voire sur LA méthode qu'on utilise en général et à laquelle je n'ai pas pensé.

    Premère solution
    • A l'ouverture d'un dossier, je scanne l'ensemble du dossier pour compter le nombre d'éléments NbFichiers (fichiers et dossiers) présents.
    • Je reviens au début avec f_rewinddir() et place mon compteur d'index NumFichier à 0.
    • Lors d'un appui sur "Précédent" :
      • je crée une variable FichierCible égale à NumFichier-1 ou NbFichiers si mon index était sur le premier fichier du dossier afin de reboucler sur la dernière entrée.
      • Je reviens au début du dossier avec f_rewinddir()
      • Je relis le dossier en séquence avec f_readdir() jusqu'à arriver à mon index FichierCible.

    Ca me parait un peu absurde. Si un dossier contient de nombreux fichiers et que l'on se trouve vers la fin de celui-ci, on va devoir rebalayer l'ensemble. Ca fait beaucoup de ressources processeur utilisées pour pas grand chose...

    Deuxième solution
    En fouinant dans le fichier ff.c du module FatFs, j'ai trouvé la fonction dir_sdi() qui sert dans f_rewinddir() et se dirige directement à l'index indiqué.
    • Donc à l'ouverture d'un dossier, je scanne toutes ses entrées, cette fois pour enregistrer les index de chaque élément dans un tableau.
    • Je reviens au début avec f_rewinddir() et place mon compteur d'index NumFichier à 0.
    • Lors d'un appui sur "Précédent", j'utilise simplement ma fonction f_readthisdir() ci-dessous

    Cette fois, l'accès à un fichier est écourté, je ne re-scanne plus tout le dossier pour trouver mon fichier.
    En revanche, je suis obligé d'utiliser un tableau d'index qui prendra plus de place en mémoire.
    J'ai cru comprendre qu'il était impossible de créer des tableaux dynamiquement alloués avec les µC, du coup, je suis également obligé de limiter le nombre de fichiers par dossier (ce qui n'est pas si problématique, ce ne serait de toutes façons pas très pratique de placer un grand nombre de fichiers dans un dossier).
    Mon code final utilise, dans la deuxième solution, beaucoup plus de ressources Data (+1000 bytes), et à quelque chose près autant de ressources Program (+300 bytes) du Pic.
    Par contre, j'imagine que le temps de traitement d'un appui sur le bouton "Précédent" sera beaucoup plus court, surtout si le dossier est gros.

    Voilà. Si vous avez un avis sur ce qu'il faut ou ne faut pas faire, je suis tout ouïe. Particulièrement si vous connaissez une méthode plus simple et/ou plus économe en ressources, évitant par exemple de scanner l'ensemble du dossier à son ouverture.

    Merci beaucoup.

    Ci-dessous, quelques bouts de code pour illustrer le problème :
    Code:
    // FONCTION f_readdir() ORIGINALE (ff.c)
    /*-----------------------------------------------------------------------*/
    /* Read Directory Entries in Sequence                                    */
    /*-----------------------------------------------------------------------*/
    
    FRESULT f_readdir (
    	DIR* dp,			/* Pointer to the open directory object */
    	FILINFO* fno		/* Pointer to file information to return */
    )
    {
    	FRESULT res;
    	DEFINE_NAMEBUF;
    
    
    	res = validate(dp);						/* Check validity of the object */
    	if (res == FR_OK) {
    		if (!fno) {
    			res = dir_sdi(dp, 0);			/* Rewind the directory object */
    		} else {
    			INIT_BUF(*dp);
    			res = dir_read(dp, 0);			/* Read an item */
    			if (res == FR_NO_FILE) {		/* Reached end of directory */
    				dp->sect = 0;
    				res = FR_OK;
    			}
    			if (res == FR_OK) {				/* A valid entry is found */
    				get_fileinfo(dp, fno);		/* Get the object information */
    				res = dir_next(dp, 0);		/* Increment index for next */
    				if (res == FR_NO_FILE) {
    					dp->sect = 0;
    					res = FR_OK;
    				}
    			}
    			FREE_BUF();
    		}
    	}
    
    	LEAVE_FF(dp->fs, res);
    }
    
    // FONCTION f_readthisdir() RAJOUTÉE POUR LA SECONDE SOLUTION (ff.c)
    #if _USE_SEEK
    /*-----------------------------------------------------------------------*/
    /* Read Directory Entries by Index                                    */
    /*-----------------------------------------------------------------------*/
    
    FRESULT f_readthisdir (
    	DIR* dp,			/* Pointer to the open directory object */
    	FILINFO* fno,		/* Pointer to file information to return */
        UINT index         /* Index of directory element to read */
    )
    {
    	FRESULT res;
    	DEFINE_NAMEBUF;
    
    
    	res = validate(dp);						/* Check validity of the object */
    	if (res == FR_OK) {
    		res = dir_sdi(dp, index);			/* Seek to the directory object */
    		if (res == FR_OK) {
    			INIT_BUF(*dp);
    			res = dir_read(dp, 0);			/* Read an item */
    			if (res == FR_NO_FILE) {		/* Reached end of directory */
    				dp->sect = 0;
    				res = FR_OK;
    			}
            }
            if (res == FR_OK) {				/* A valid entry is found */
                get_fileinfo(dp, fno);		/* Get the object information */
                res = dir_next(dp, 0);		/* Increment index for next */
                if (res == FR_NO_FILE) {
                    dp->sect = 0;
                    res = FR_OK;
                }
    			FREE_BUF();
    		}
    	}
    
    	LEAVE_FF(dp->fs, res);
    }
    #endif
    
    // FONCTION DE SCANNAGE DES INDEX POUR LA SECONDE SOLUTION (Main.c)
    /*--------------------------------------------------------------------------------------*/
    /* Scanne un dossier et enregistre l'index de chaque élément        */
    /*--------------------------------------------------------------------------------------*/
    
    FATFS FatFs;        // FatFs work area needed for each volume
    DIR Dossier;        // Dossier actuellement parcouru
    FILINFO Fichier;    // Informations du fichier pointé
    UINT Index[255], NumFichier, NbFichiers;
    
    static FRESULT ScanDir(void){
        
        FRESULT res;
        UINT currentIndex;
        Index[0] = NumFichier = 0;
        
        do {
            NumFichier++;
            do {
                currentIndex = Dossier.index;   // Dossier.index indique en fait l'index du fichier suivant à cause de l'appel à dir_next()
                                                                 // Donc on enregistre l'index avant de scanner l'élément suivant
                res = f_readdir(&Dossier, &Fichier);
                if (res != FR_OK) return res;
            } while (Fichier.fname[0] == '.');   // On saute les fichiers cachés (on le fera également lors de la lecture f_readdir())
            
            if (Fichier.fname[0] != 0) Index[NumFichier] = currentIndex;
            else Index[NumFichier] = 0;
        } while (Fichier.fname[0] != 0);
        
        NbFichiers = NumFichier - 1;
        res = f_rewinddir(&Dossier);
        NumFichier = 0;
        return res;
    // FONCTION PRECEDENT (Main.c)
    /*--------------------------------------------------------------------------------------*/
    /* Cheche le fichier précédent        */
    /*--------------------------------------------------------------------------------------*/
    FRESULT ReadPrev(void) {
        FRESULT res;
        
        if (NumFichier < 2) NumFichier = NbFichiers;
        else NumFichier--;
        
        res = f_readthisdir (&Dossier, &Fichier, Index[NumFichier]);
        if (Fichier.fname[0] == 0) return FR_NO_FILE; 
        
        return res;
    }
    }

    -----
    Dernière modification par scaypapa ; 07/12/2016 à 12h04.

  2. #2
    scaypapa

    Re : Navigation dans un système de fichier Fat

    ... oops, une petite erreur dans le code s'est glissée et je ne peux plus modifier... Évidemment, la fonction ReadPrev() se trouve après la fermeture de la fonction ScanDir()

  3. #3
    scaypapa

    Re : Navigation dans un système de fichier Fat

    ... up ...

    Vous n'avez pas d'avis sur la question ?

  4. #4
    invite5637435c

    Re : Navigation dans un système de fichier Fat

    Citation Envoyé par scaypapa Voir le message
    Mon but serait d'avoir 4 boutons : fichier/dossier suivant, fichier/dossier précédent, ouvrir et fermer. Rien d'exceptionnel quoi, je ne pense pas être le premier à vouloir faire ça.
    Sauf que malgré des heures de recherche, je ne trouve pas de moyen "simple" d'implémenter la fonction "Précédent". Les éléments d'un dossiers sont lus dans l'ordre séquentiel et on ne peut pas revenir en arrière.
    Je suis très surpris de ne trouver aucune doc ou aucun tuto sur ce sujet dans les méandres du web...
    Bonjour,
    je ne vois pas bien ce qui te surprend à propos du web.
    Bon nombre de sujets ne sont pas abordés du tout, et un tout petit pourcentage est réellement pertinent.
    Un forum n'est pas un self service R&D comme certains aimeraient, à partir d'un certain niveau ça se paye, comme toute chose dans la vraie vie...
    Sinon tu as wikipédia!
    Nan je déconne

    J'ai cru comprendre qu'il était impossible de créer des tableaux dynamiquement alloués avec les µC


    Tu as été mal informé, c'est juste beaucoup plus complexe selon le µC.


  5. A voir en vidéo sur Futura

Discussions similaires

  1. Réponses: 43
    Dernier message: 24/01/2016, 19h21
  2. DM:système de navigation inertiel
    Par invited622d663 dans le forum Physique
    Réponses: 0
    Dernier message: 16/10/2012, 14h40
  3. systeme de navigation inertielle
    Par invitebc4751bf dans le forum Astronautique
    Réponses: 0
    Dernier message: 09/07/2006, 02h33
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...