IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MATLAB Discussion :

Récupération des données à l'aide de fread et fseek [Débutant]


Sujet :

MATLAB

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut Récupération des données à l'aide de fread et fseek
    Bonjour à tous,

    C'est encore moi ! J'ai à présent un problème un peu plus subtile que je souhaiterais résoudre. Je suis en train d'écrire une fonction qui est chargée de récupérer des données à l'aide de fread mais seulement entre certaines bornes prédéfinies. J'ai écrit un code qui fonctionne mais je ne suis pas sûr de récupérer effectivement les données au bon endroit.

    Je m'explique, voici d'abord le code simplifié et les commentaires juste après :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function X=lire_50(repertoire,debut,fin)
    debut=(1 + 50*(debut-1));
    fin=50*fin;
    nomfichier0=strcat('C:\MATLAB701\work\IMP\DATA\',repertoire,'\',repertoire,'-50\','Imp1.int');
    fid0=fopen(nomfichier0);
    fseek(fid0,2*debut,'bof');
    valeurs_Imp1=fread(fid0,(fin-debut),'short');
    Cette fonction prend en paramètre un certain répertoire et des nombres début et fin. Dans la fonction je calcule de nouvelles valeurs entre début et fin, par exemple disons que j'ai debut=1000 et fin=2000. Ensuite, je recherche un répertoire à l'aide du strcat qui contient des données que je veux exploiter depuis un fichier .int (peu importe le format .int, j'ai simplement des données stockées dedans qu'il me faut récupérer). Je l'ouvre (fopen) puis à l'aide du fseek et de fread je voudrais simplement lire ce .int entre debut et fin.

    Il se trouve que tel que j'ai écris ces lignes, le code fonctionne mais ne semble pas lire les vraies données. Sans le fseek, cela marche aussi mais ce qui est dans valeurs_Imp1 est clairement faux. En effet si je rajoute une ligne valeurs_Imp1_bis=fread(fid0,'short') et qu'ensuite je fais quelque chose comme valeurs_Imp1_bis(debut:fin) je n'obtiens pas les mêmes résultats qu'en intégrant directement fin-debut dans le fread. Bref le problème vient sans doute du fseek et de l'usage du 'short' dans le fread dont je ne peux pas me passer dans le contexte.

    Bref, pour résumer c'est assez simple : il faut imaginer que dans le .int j'ai une colonne de données et que je cherche à récupérer seulement ces données entre début et fin, moyennant les problèmes induits par 'short'. J'ai besoin de faire ceci car la fonction va être appelée une bonne centaine de fois
    et je voudrais m'éviter de récupérer toutes les données dans valeurs_Imp1 (il y a des millions de nombres dans les .int) mais seulement ce qui nécessaire entre début et fin à chaque fois.

  2. #2
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Entre temps j'ai effectué des tests afin de voir ce qui pose problème dans le code. A priori c'est bien le fseek qui est en cause. En effet :

    D'abord ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    function X=lire_50(repertoire,debut,fin)
    nomfichier0=strcat('C:\MATLAB701\work\IMP\DATA\',repertoire,'\',repertoire,'-50\','Imp1.int');
    fid0=fopen(nomfichier0);
    valeurs_Imp1=fread(fid1,'short');
    valeurs_Imp1bis=valeurs_Imp1(debut:fin);
    Ceci donne les bonnes valeurs entre debut et fin que j'attends mais je lis toutes les valeurs avec le fread puis je sélectionne celle entre les deux bornes mais justement je voudrais éviter d'avoir à lire toutes les données d'abord.

    Ensuite ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    function X=lire_50(repertoire,debut,fin)
    nomfichier0=strcat('C:\MATLAB701\work\IMP\DATA\',repertoire,'\',repertoire,'-50\','Imp1.int');
    fid0=fopen(nomfichier0);
    valeurs_Imp1=fread(fid0,(fin-debut+1),'short');
    Cette variante ne marche pas : j'obtiens certes des valeurs dans valeurs_Imp1 mais je ne sais pas exactement desquelles il s'agit, en tout cas pas de celles entre debut et fin.

    Enfin la dernière varainte en ajoutant fseek :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    function X=lire_50(repertoire,debut,fin)
    nomfichier0=strcat('C:\MATLAB701\work\IMP\DATA\',repertoire,'\',repertoire,'-50\','Imp1.int');
    fid0=fopen(nomfichier0);
    fseek(fid0,2*debut,'bof');
    valeurs_Imp1=fread(fid0,(fin-debut),'short');
    Cela ne marche pas tout à fait et je ne comprends pas pourquoi : en gros au lieu d'obtenir les résultats entre debut et fin, je les obtiens entre debut+1 et fin et il manque donc la première valeur. Rien n'y fait, que je fasse fin-(debut-1) ou autres combinaisons ce décalage reste le même. Que faire ?

    EDIT:

    En fait en mettant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fseek(fid0,2*(debut-1),'bof');
    Il semble qu'après plusieurs tests j'obtienne bien les résultats escomptés. Malgré tout je crois que je ne comprends pas bien le fonctionnement de fseek car je serai incapable de dire pourquoi la lecture s'effectue bien comme je le voudrais. De plus il y a quelque chose que j'ignore : admettons que le segment [debut:fin] soit en dehors des valeurs de valeurs_Imp1 : par exemple valeurs_Imp1 possède 1000 élément et je demande debut=900 et fin=2000, va-t-il me renvoyer valeurs_Imp1 entre 900 et 1000 ?

  3. #3
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 302
    Points : 53 160
    Points
    53 160
    Par défaut
    Pour lire des fichiers binaires (avec fread et fseek) il faut connaitre le format des données qui y sont écrites.

    Si je comprends bien, chaque fichier est simplement constitué d'une suite de valeurs numériques. Avec quelle précision sont-elles écrites ? Voir la documentation de la fonction fread
    Ingénieur indépendant en mécatronique - Conseil, conception et formation
    • Conception mécanique (Autodesk Fusion 360)
    • Impression 3D (Ultimaker)
    • Développement informatique (Python, MATLAB, C)
    • Programmation de microcontrôleur (Microchip PIC, ESP32, Raspberry Pi, Arduino…)

    « J'étais le meilleur ami que le vieux Jim avait au monde. Il fallait choisir. J'ai réfléchi un moment, puis je me suis dit : "Tant pis ! J'irai en enfer" » (Saint Huck)

  4. #4
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    Oui Dut, merci, c'est bien ce format qui joue. Et bien, pour résumé, déjà le code que j'ai mis dans le edit fonctionne bien mais j'ai l'impression d'être "chanceux".

    Ensuite voici comment j'ai procédé dès le départ : au départ, j’ai un fichier .CSV que je lis d'une certaine manière avec un autre programme que celui dont je parle ici et je stocke dans des .int les données qui m'intéresse dedans.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fwrite(fid0,S2(1),'short');
    fid0 est le fichier .int à créer et S2(1) ce qui m'intéressait dans le .CSV et que j'écris donc dans ce .int, à savoir un vecteur colonne en l'occurence. Et c'est tout. Ensuite je peux passer directement à la lecture comme je viens de le faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function X=lire_50(repertoire,debut,fin)
    nomfichier0=strcat('C:\MATLAB701\work\IMP\DATA\',repertoire,'\',repertoire,'-50\','Imp1.int');
    fid0=fopen(nomfichier0);
    fseek(fid0,2*(debut-1),'bof');
    valeurs_Imp1=fread(fid0,(fin-debut),'short');
    En mettant bien debut-1 dans le fseek et fin-debut dans le fread, je lis effectivement le contenu du .int entre les bornes debut et fin comme je le voulais. Si je ne mets pas 2*(debut-1) cela ne marche pas évidemment. Bref, je ne comprends pas très bien pourquoi mais bon.

  5. #5
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 302
    Points : 53 160
    Points
    53 160
    Par défaut
    Tu es obligé de multiplier par 2 car fseek prend comme argument une position en octets et que les valeurs dans le fichier sont codées en short donc sur 2 octets.

    Pour le début-1, c'est logique puisque la valeur doit correspondre à la position du curseur dans le fichier avant lecture.

    Si tu veux lire la première valeur du fichier, il faut faire :
    Si tu veux lire la deuxième valeur du fichier, il faut faire :
    Si tu veux lire la troisième valeur du fichier, il faut faire :
    ...
    Ingénieur indépendant en mécatronique - Conseil, conception et formation
    • Conception mécanique (Autodesk Fusion 360)
    • Impression 3D (Ultimaker)
    • Développement informatique (Python, MATLAB, C)
    • Programmation de microcontrôleur (Microchip PIC, ESP32, Raspberry Pi, Arduino…)

    « J'étais le meilleur ami que le vieux Jim avait au monde. Il fallait choisir. J'ai réfléchi un moment, puis je me suis dit : "Tant pis ! J'irai en enfer" » (Saint Huck)

  6. #6
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 401
    Points : 102
    Points
    102
    Par défaut
    D'accord, pour le 2 je pensais également avoir compris : short correspond à 16 bits d'après l'aide ici http://www.mathworks.fr/fr/help/matlab/ref/fread.html et comme tu dis que fseek travaille sur 1 octet=8Bits, on multiplie donc bien par 2.

    Ensuite, si je comprends bien la position "0" existe dans fseek et indique le curseur afin d'arriver sur la position "1", début de la lecture. Ceci me trouble car en Matlab je ne crois pas qu'il existe d'indice 0, par exemple sur un vecteur X(0) renvoie une erreur. Est-ce donc ici une sorte d'exception ? Le comportement semble similaire à un pointeur qui se place où on le souhaite dans le fichier à lire et qui aurait une position "0" que je qualifierait de "position par défaut" hors pointage.

  7. #7
    Rédacteur/Modérateur

    Avatar de Jerome Briot
    Homme Profil pro
    Freelance mécatronique - Conseil, conception et formation
    Inscrit en
    Novembre 2006
    Messages
    20 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance mécatronique - Conseil, conception et formation

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 302
    Points : 53 160
    Points
    53 160
    Par défaut
    C'est écrit dans la documentation :

    offset : Number of bytes to move from origin. Can be positive, negative, or zero. The n bytes of a given file are in positions 0 through n-1.
    Pour se placer au début du fichier, il faut bien dire à MATLAB de se déplacer avec fseek de 0 octet, non ?
    Ingénieur indépendant en mécatronique - Conseil, conception et formation
    • Conception mécanique (Autodesk Fusion 360)
    • Impression 3D (Ultimaker)
    • Développement informatique (Python, MATLAB, C)
    • Programmation de microcontrôleur (Microchip PIC, ESP32, Raspberry Pi, Arduino…)

    « J'étais le meilleur ami que le vieux Jim avait au monde. Il fallait choisir. J'ai réfléchi un moment, puis je me suis dit : "Tant pis ! J'irai en enfer" » (Saint Huck)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/09/2010, 23h17
  2. récupération des données via une liste déroulante
    Par rahan_dave dans le forum Access
    Réponses: 1
    Dernier message: 13/10/2005, 13h27
  3. [HTML][FORMULAIRE] Probleme dans la récupération des données
    Par baddounet dans le forum Balisage (X)HTML et validation W3C
    Réponses: 6
    Dernier message: 15/08/2005, 19h51
  4. Réponses: 2
    Dernier message: 20/02/2004, 09h47
  5. Réponses: 13
    Dernier message: 20/03/2003, 09h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo