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

C Discussion :

Lecture/écriture fichier binaire via structure


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Points : 41
    Points
    41
    Par défaut Lecture/écriture fichier binaire via structure
    Bonsoir.
    Dans le cadre de mes études, je dois réaliser un projet en langage C. J'en suis à la phase d'analyse, c'est-à-dire que je suis entrain de réfléchir à comment mettre en place le tout. J'ai cependant quelques questions à vous soumettre car je ne vois pas bien comment mettre en œuvre certaines choses.

    Dans le programme en question, je devrai notamment écrire des informations dans un fichier binaire en passant par une structure, j'entends par là que l'utilisateur rentrera les informations, lesquelles seront stockées dans une structure avant d'écrire cette structure dans le fichier binaire. Pareil pour la lecture, je dois pouvoir lire un fichier binaire et garnir une structure à partir des informations lues. Dans le fichier, il y aurait un enregistrement par ligne (j'appelle ça un enregistrement, certains seront peut-être plus à l'aise avec le terme "record") et chaque info serait séparée par un espace. Évidemment, j'entends par "ligne" le fait d'appuyer sur Enter, donc un Carriage Return.

    Pour donner un exemple, imaginons que j'aie une structure nommée "Client" dans laquelle plusieurs champs sont présents. Certains seraient de type char (plus exactement tableau de char) comme le nom, le prénom etc. D'autre de types int, float. Un utilisateur entre ses informations personnelles que je récupère via cette structure et ensuite je vais écrire le contenu de cette dernière dans un fichier client.dat par exemple. I faudrait donc que toutes les informations soient reprises dans le fichier et que chaque champ présent dans la structure soit séparé par un espace dans le fichier.

    Je ne vois pas trop comment implémenter ce mécanisme, j'ai un peu d'expérience en C mais je n'ai pas encore fait de programmes de ce type. Si quelqu'un pouvait éclairer ma lanterne, je lui en serais reconnaissant.
    Merci d'avance et bonne soirée.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Bienvenue sur le forum,

    Il y a une ambiguïté dans ce que tu dis : tu parles de faire un fichier binaire, et ensuite tu parles de lignes. Un fichier organisé en ligne est un fichier texte par définition.
    Si tu as un fichier texte, tes données doivent être écrites en texte, pas sous forme binaire (pour les int, float ...), sinon il risquerait d'y avoir des blancs ou des fins de ligne intempestifs. Dans ce cas, le code est simple. Un exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct X
    {
       char nom[30];
       int age; 
    }unX = {"MonNom", 100};
     
    fprintf(stdout, "%s %d\n", unX.nom, unX.age);
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Points : 41
    Points
    41
    Par défaut
    Au temps pour moi, je travaille bien avec des fichiers binaires et non des fichiers textes. Comment faire dans ce cas-là ?

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Bonsoir,

    Citation Envoyé par Tenebrous Voir le message
    Pour donner un exemple, imaginons que j'aie une structure nommée "Client" dans laquelle plusieurs champs sont présents. Certains seraient de type char (plus exactement tableau de char) comme le nom, le prénom etc. D'autre de types int, float. Un utilisateur entre ses informations personnelles que je récupère via cette structure et ensuite je vais écrire le contenu de cette dernière dans un fichier client.dat par exemple. I faudrait donc que toutes les informations soient reprises dans le fichier et que chaque champ présent dans la structure soit séparé par un espace dans le fichier.

    Je ne vois pas trop comment implémenter ce mécanisme, j'ai un peu d'expérience en C mais je n'ai pas encore fait de programmes de ce type. Si quelqu'un pouvait éclairer ma lanterne, je lui en serais reconnaissant.
    Merci d'avance et bonne soirée.
    Si tes structures sont de taille fixe (et elles le sont toujours), tu n'as pas besoin de séparateur dans ton fichier. Tu peux enregistrer bout-à-bout chaque structure et te déplacer ensuite dans ton fichier à une position multiple de de la taille de ta structure.

    À dire vrai, c'est exactement à ça que sert l'interface originelle des fichiers en C. À la base, un « fichier », c'est une boîte à fiches, et c'est à cet usage qu'étaient initialement destinés les fichiers informatiques. Si l'on regarde la man page de fread() et fwrite(), on s'aperçoit qu'elles attendent en argument la taille d'un membre et le nombre de membres à lire ou à écrire, ceci afin de te renvoyer un nombre entier de membres entièrement lus ou écrits.

    Il te suffit donc de déclarer une structure, de la remplir éventuellement, et d'utiliser l'une ou l'autre de ces fonctions en passant l'adresse de la structure déclarée avec « & », pour qu'elles aillent directement y chercher les données à écrire ou déposer les données lues.

    Seul détail : veille à utiliser des tableaux de caractères dans ta structure et non des pointeurs vers des chaînes de caractères se trouvant en dehors. Autrement, le contenu de ton pointeur serait bien enregistré, mais ne correspondrait plus à rien à la relecture.

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Le soucis c'est que, si on copie à la volée une structure dans un fichier, ça pose un gros problème de portabilité. Il y a une contrainte liée aux questions de l'alignement, du boutisme et de la taille des types (qui peut varier).

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 372
    Points : 23 628
    Points
    23 628
    Par défaut
    Citation Envoyé par jeroman Voir le message
    Le soucis c'est que, si on copie à la volée une structure dans un fichier, ça pose un gros problème de portabilité. Il y a une contrainte liée aux questions de l'alignement, du boutisme et de la taille des types (qui peut varier).
    Gros oubli de ma part, effectivement. Je comptais commencer par cela et j'ai purement et simplement esquivé l'avertissement principal.

    Donc, comme le dit Jeroman, cette méthode ne fonctionne qu'à partir du moment où les données restent exploitées sur la même machine et par le même logiciel. À partir du moment où l'on change de version du compilateur, on ne peut même plus garantir à 100% que l'alignement des données correspondra encore. Sauf à utiliser #pragma pack(1) et à utiliser des types au format fixe tels que int32_t, qui permettent au moins de garantir la position des données dans le fichier.

    Le plus propre reste d'écrire les données au format texte, précédé du nom de leur champ, de faire un lecteur qui remplisse la structure champ par champ et qui la renvoie, en précisant éventuellement si celle-ci a été partiellement ou totalement remplie. Mais ça demande un peu plus de travail.

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Points : 41
    Points
    41
    Par défaut
    Merci à tous pour vos messages et précisions, j'y vois beaucoup plus clair désormais.
    Cordialement.

  8. #8
    Membre du Club
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 65
    Points : 41
    Points
    41
    Par défaut
    Je suis occupé à réaliser quelques tests et malheureusement tout ne se passe pas comme je le voudrais.
    Voici un code que j'ai réalisé vite fait pour tester ce qui a été dit plus haut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    #include <stdio.h>
    #include <myconio.h>
    #include "structures.h"   /** contient la structure client **/
     
    void GesCli(Client *cli);
    void struct_to_file(Client *cli, FILE *fichier);
     
    int main(void)
    {
        FILE *client = NULL;
        Client cli;
     
        if ((client = fopen("client.dat", "wb")))   /** si ouverture ok **/
        {
        GesCli(&cli);
        struct_to_file(&cli, client);
        }
        else
            printf("Erreur\n\n");
        return 0;
    }
     
    void GesCli(Client *cli)
    {
        gotoxy(30,1);
        printf("Gestion clients");
        gotoxy(5, 5);
        printf("\nNom : ");
        scanf("%s", cli->cl_nom);
        printf("\nPrenom : ");
        scanf("%s", cli->cl_prenom);
        printf("\nRue et numero : ");
        scanf("%s", cli->cl_rue_no);
        printf("\nCode postal : ");
        scanf("%s", cli->cl_cp);
        printf("\nLocalite : ");
        scanf("%s", cli->cl_loc);
        printf("\nPays : ");
        scanf("%s", cli->cl_pays);
        printf("\nNumero de fixe : ");
        scanf("%s", cli->cl_tel);
        printf("\nNumero de portable : ");
        scanf("%s", cli->cl_tel2);
        printf("\nEmail : ");
        scanf("%s", cli->cl_email);
    }
     
    void struct_to_file(Client *cli, FILE *fichier)
    {
        Client g;
     
        fwrite(cli, sizeof(cli), 1, fichier);
        puts("ecriture ok\n\n");
        /** pour verifier si nom prenom et rue s affiche bien **/
    	fread(&g, sizeof(cli), 1, fichier);
    	fclose(fichier);
    	printf("resultat : %s %s %s\n", g.cl_nom, g.cl_prenom, g.cl_rue_no);
    }
    Au printf qui doit normalement m'afficher le nom, prénom et la rue, ce sont en fait de drôles de caractères qui sont présents (sortes de caractères spéciaux).
    Quelqu'un peut-il m'éclairer une seconde fois ?
    Merci d'avance.

  9. #9
    Membre éclairé
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Points : 842
    Points
    842
    Par défaut
    Ton problème vient de la fonction struct_to_file.

    *) Tu écris sizeof(cli) mais sizeof(cli) vaut la taille d'un pointeur et pas la taille de ta structure.

    *) Tu fais un fread juste après ton fwrite, il serait plus judicieux de revenir au début de ton fichier avant de lire non ?
    Plus tu pédales moins fort, moins t'avances plus vite.

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    J'ajouterais que tu as ouvert ton fichier en ecriture seule.

Discussions similaires

  1. Structures C, perl et lecture de fichier binaires
    Par bulki dans le forum Langage
    Réponses: 1
    Dernier message: 24/08/2009, 17h02
  2. lecture ecriture fichier binaire
    Par jonckers dans le forum C++Builder
    Réponses: 2
    Dernier message: 27/04/2007, 09h12
  3. Réponses: 5
    Dernier message: 26/03/2007, 01h30
  4. écriture fichier binaire
    Par alex'l dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 31/01/2007, 15h43
  5. lecture de fichier binaire
    Par Salim6 dans le forum C
    Réponses: 3
    Dernier message: 07/11/2005, 19h56

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