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 :

lire un fichier en mode binaire et le recopier


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2015
    Messages : 12
    Par défaut lire un fichier en mode binaire et le recopier
    Bonjour,

    Je suis un débutant en C et je suis bloqué sur un programme. Je dois réaliser un projet qui consiste à créer une commande pour archiver des fichiers. Pour cela, je dois pouvoir stocker dans un seul fichier les contenus et information de plusieurs fichiers. Cependant je n'arrive pas à récupérer le contenu d'un fichier à archiver.
    Donc j'ai ma structure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct fichier_info{
            size_t path_length; //ok
    	off_t file_length;
            mode_t mode; //ok
            time_t m_time; //ok
            time_t a_time; //ok
            char *nom_file;  //ok
    	char checksum[32]; // osef 
            char path[100]; //ok
    	char* file;
    };
    Dans la consigne qu'on me donne, je dois avoir un type char[] pour le champ file, mais je ne sais pas comment je peux définir la taille de file en avance ! Vu que c'est dans une structure, je ne vois pas comment je pourrais allouer un tableau dynamique... Donc j'ai essayé avec char* pour récupérer des chaines de caractère dans file.
    Je n'ai pas de problème pour la plupart des champs, checksum représente l'empreinte md5 du fichier. Je ne sais pas ce que c'est parce que je ne me suis pas encore renseigné, mais je laisse ca de coter pour l'instant. Ce qui me dérange pour l'instant, c'est de pouvoir recopier le contenu d'un fichier dans le champ file. Je ne veux pas écrire directement le contenu dans un fichier, je voudrais qu'il soit dans la structure car c'est demandé dans la consigne et que pour extraire ca serait plus pratique.

    Avant de vous montrer ma fonction archivage, je vous montre le fichier .txt que je tente d'archiver :
    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
     
    ca gaz ou quoi ??.
     
     
    f
    ezfùe
    cef
    vsd
    v
    ea
    gz
    rds
     
    sdv
    ds
    lol
    Puis ma fonction archivage :
    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
     
    void archivage(int c, char *arg[], int fn, int dd, int d)
    {
      // Pas besoin de s'occuper de fn, dd, d et c. arg[3] contient le fichier à archiver, et arg[2] le nom du fichier d'archive.
      struct fichier_info tab_info;
      printf("Fonction archivage\n");
    	int len,archive,i;
    	FILE* dc; char buf[1024];
    	dd = c-3;
    	char *r = "rb";
    	// J'ouvre le fichier archive (ou je le créé)
    if((archive=open(arg[2],O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,S_IRWXU|S_IRWXG|S_IRWXO))<0)
                       exit(1);
           //Cette boucle permet de prendre plusieurs arguments mais on s'en fout
    	for(i=3;i<c;i++)
    	  {
    	    //  Ouverture du fichier à archiver avec fopen (ouverture en binaire car r = "rb"
    	        struct stat st;
    		if((stat(arg[i],&st) != 0)|((dc = fopen(arg[i],r))<0))
    		{
    			printf("impossible d archiver %s ",arg[i]);
    			continue;
    		}
    		// On complète la structure tab_info à partir d'ici
    		tab_info.nom_file=arg[i]; char s[] ="okok";
    		printf("nom fichier : /! %s  /!  \n", tab_info.nom_file);
    		strcpy(tab_info.path,chemin(arg[i]));
    		printf("chemin : %s\n", tab_info.path);
    		tab_info.path_length=strlen(tab_info.path)+1;
                    strcat(tab_info.path,"\0");
    		tab_info.mode=st.st_mode;
    		tab_info.a_time=st.st_atime;
    		tab_info.m_time= st.st_mtime;
    		// C'est ici que je tente d'insérer le contenu du fichier dans tab_info.file
    		while(fread(buf,1024,1,dc)> 0) 
    		  {
    		    printf(">>>>>  CC  <<<<<\n");
    		    tab_info.file = strcat(tab_info.file, buf);
    		  }
           	        tab_info.file_length=st.st_size;
     
    		printf("file : \n%s\nBuf : %d\n",tab_info.file);
     
    	       	write(archive,&tab_info,sizeof(struct fichier_info));
    		fclose(dc);
    	}
    	close(archive);
    }

    Et la il se passe un truc de fou, dans le while avec lequel j'appelle fread, CC ne s'affiche pas, donc on ne rentre pas dans la boucle (c'est sur, j'ai bien vérifié). MAIS le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("file : \n%s\nBuf : \n",tab_info.file);
    affiche ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    file : 
    s
     
    sdv
    ds
    lol
    Quand je mets toute la boucle while en commentaire, tab_info.file affiche des caractères bizarres (5-6 caractères hiéroglyphe). Donc du coup je ne pige que dalle, strcat remplirait tab_info.file de la fin du fichier alors qu'on entre même pas dans la boucle (quand elle n'est pas en commentaire)? Mais pourquoi ? Je suis sur qu'il y a une explication logique à cela, mais pour moi ca me semble complètement illogique ! fread ne touche pas à tab_info.file, rien ne devrait changer. Même en mettant fread tout seul, sans le strcat, la même chose s'affiche ! ... ?

    Bref vous l'aurez compris, ca me pique le crâne fortement cette histoire donc j'ai besoin de votre aide svp ! Merci d'avance



    EDIT : J'ai utilisé deux différents open parce que je ne vois pas comment ouvrir en mode binaire avec open, et je n'ai pas vu de fonction tel que fopen, fread et fwrite en cours. Et je viens de modifier le dernier paragraphe qui donnait une fausse information.

    EDIT 2 : Je n'ai pas le droit d'utiliser LA fonction system !

  2. #2
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 872
    Par défaut
    EDIT 2 : Je n'ai pas le droit d'utiliser des fonctions système !
    open/read/write/close étant des fonctions systèmes, t'es mal barré.

    J'ai utilisé deux différents open parce que je ne vois pas comment ouvrir en mode binaire avec open, et je n'ai pas vu de fonction tel que fopen, fread et fwrite en cours. Et je viens de modifier le dernier paragraphe qui donnait une fausse information.
    En C, on peut dire que les fichiers sont toujours ouverts en mode binaire, il n'y a aucun traitement sur les données lues/écrites exceptés ceux que tu mettras en place. Concernant fopen, fread, fwrite et fclose (ne pas l'oublier !), il te suffit de lire leur manuel respectif dont je t'ai fourni les liens). Je recommande d'ailleurs leur usage plutôt que celui d'open/read/etc...

    Maintenant pour lire le contenu de ton fichier, plusieurs questions se posent :

    1. Est-ce que tu effectues un traitement sur les données lues / écrites ?
    2. As-tu réellement besoin d'avoir l'intégralité de ton fichier dans un seul buffer ?

    Si la réponse à la question 1. est non, tu n'as absolument pas besoin de tout stocker dans un seul buffer, il te suffit de faire un buffer tampon. Explications : en gros tu lis 10 caractères (ce nombre importe peu) et tu les recopies aussitôt dans le nouveau fichier. Tu continues jusqu'à avoir atteint la fin du fichier lu. Félicitations, tu as copié un fichier !

    Si la réponse à la question 1. est oui, je pense que la réponse sera la même pour la question 2. Dans ce cas, il t'est possible de récupérer la taille d'un fichier comme indiqué ici. Ensuite, il te suffit de faire un malloc de la taille retournée et de lire le fichier d'un seul coup. Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    off_t size = get_size();
     
    char *buffer = malloc(sizeof(*buffer) * size);
    fread(buffer, sizeof(*buffer), size, fd);
    fwrite(buffer, sizeof(*buffer), size, new_fd);
    Voilà, j'espère que ça t'aidera.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2015
    Messages : 12
    Par défaut
    Désolé, c'est la fonction system, pas les fonctions système.

    Ce que je veux faire, c'est pouvoir mettre le contenu du fichier dans ma structure puisque après je vais devoir extraire les fichiers de l'archive. Si j'écris directement, je ne sais pas comment je pourrais récupérer le contenu d'un fichier, ca risque d'être le bazar ! Donc non je ne modifie pas les données lues ou écrites, mais j'ai besoin "d'ordonner" le contenu du fichier. Ainsi, pour le récupérer il suffira que je read dans un fichier des structures fichier_info.

    Mais je vais tenter d'utiliser ton code et de copier le buffer dans mon tab_info.file, merci !

    EDIT : Enfin je n'aurais même pas besoin de copier le buffer, j'utilise directement tab_info.file comme buffer

  4. #4
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2015
    Messages : 12
    Par défaut
    Merci ca fonctionne parfaitement !

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Zulhuky Voir le message
    Bonjour,
    Bonjour,

    Citation Envoyé par Zulhuky Voir le message
    Je suis un débutant en C
    et t'as pas remarqué qu'il y avait une rubrique spécial débutant ???


    Citation Envoyé par Zulhuky Voir le message
    Dans la consigne qu'on me donne, je dois avoir un type char[] pour le champ file, mais je ne sais pas comment je peux définir la taille de file en avance !
    Tu peux pas. Soit tu admets que ton champ ne pourra pas dépasser une certaine taille max et tu crées un champ ayant cette taille, soit tu alloues après avoir récupéré la taille nécessaire.

    Citation Envoyé par Zulhuky Voir le message
    Vu que c'est dans une structure, je ne vois pas comment je pourrais allouer un tableau dynamique...
    Je ne vois pas ce que ça change. Tu peux accéder et allouer un champ de structure au même type qu'une variable simple...
    Exemple d'allocation
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char *tab1;
    struct {
        int *tab2;
    } ma_var;
     
    tab1=malloc(10 * sizeof(char));
    ma_var.tab2=malloc(20 * sizeof(int));
    free(tab1);
    free(ma_var.tab2);

    Citation Envoyé par Zulhuky Voir le message
    Ce qui me dérange pour l'instant, c'est de pouvoir recopier le contenu d'un fichier dans le champ file. Je ne veux pas écrire directement le contenu dans un fichier, je voudrais qu'il soit dans la structure car c'est demandé dans la consigne et que pour extraire ca serait plus pratique.
    T'es sûr ??? Si t'as un fichier iso de 40G (taille d'un des dernier call of duty par exemple) tu vas te le recopier dans ta structure ??? Tu vas exploser ta RAM...

    Citation Envoyé par Zulhuky Voir le message
    EDIT : J'ai utilisé deux différents open parce que je ne vois pas comment ouvrir en mode binaire avec open, et je n'ai pas vu de fonction tel que fopen, fread et fwrite en cours.
    Si t'es sous Unix/Linux (qui considère tout fichier comme étant binaire) t'as rien à faire. Sous Windows (qui fait chier tous les programmeurs du monde avec sa différence texte/binaire que rien ne justifie) tu rajoutes le flag O_BINARY dans tes flags d'ouverture.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2015
    Messages : 12
    Par défaut
    Bon mon archive a toujours la même taille (192 octets), même si je ne mets rien dans tab_info... J'ai l'impression que c'est impossible d'écrire une structure dans un fichier non ? La taille devrait varier en fonction de ce qu'il y a dans tab_info.file ? J'ai tenté d'archiver un fichier de 3Go, ca a mis du temps (p-e 3 minutes) mais mon fichier archive fait toujours 192 octets...
    Donc j'en conclus que c'est impossible de contenir le fichier dans tab_info.file, mais dans ce cas là, comment je peux m'y retrouver si je concatène plein de contenu de fichier et avec leurs informations ? La structure me permet de facilement extraire, mais sans structure je ne vois pas comment faire ?

    EDIT : oui je suis sous linux

  7. #7
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Ne serait-ce pas l'obligation d'écrire une structure détaillant le fichier suivie dudit fichier, et tout ça répété autant de fois que de fichiers ?
    Car stocker les données du fichier dans la structure, ça n'a aucun sens.
    La commande tar procède ainsi : informations du fichier puis données du fichier, et ça recommence jusqu'à stocker toutes les données des fichiers dans un seul fichier.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  8. #8
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2015
    Messages : 12
    Par défaut
    Ca n'est pas dit explicitement que l'on doit faire une structure pour les informations du fichier, mais ca me semblait évident. En tout cas je suis sur que je ne peux pas contenir le contenu du fichier dans une variable. Je vais faire ce que tu m'as dit dinobogan, cad une structure pour les infos, puis le contenu hors de la structure. Mais ca sera bien plus galère pour l'extraction

    EDIT : Du coup je vais devoir faire un buffer avec une taille limité et dans une boucle while pour recopier le contenu d'un fichier, cad faire un read et write jusqu'à ce que read retourne 0

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Zulhuky Voir le message
    J'ai l'impression que c'est impossible d'écrire une structure dans un fichier non ? La taille devrait varier en fonction de ce qu'il y a dans tab_info.file ?
    Non. Une structure est une suite de variables liées de façon logique (comme par exemple nom+prénom+adresse pour une personne). La taille d'une structure est fixe et est alors la somme des tailles des variables qui la composent. Même si un des champs est un pointeur alloué, la taille reste figée (taille du pointeur, la zone allouée étant ailleurs dans la mémoire).

    Quand au stockage c'est ce qu'on nomme "sérialisation". Il y a plusieurs techiques
    • tu bazardes la structure en vrac dans ton fichier (write(&structure, sizeof structure, fp). De l'autre coté tu récupères bien évidemment tous les octets composant la structure que tu reclaques dans une structure analogue. Ca fonctionnera si tu restes dans la même architecture (car certains compilos rajoutent des octets bidons dans les structures pour les faire "coller" avec l'architecture de l'OS et donc entre deux OS différents ça peut changer). Mais ça ne fonctionnera pas si la structure contient une zone allouée (laquelle se trouve placée dans un autre emplacement mémoire). Dans ce cas, de l'autre coté tu récupères une adresse ne correspondant à rien de concret
    • tu descends les éléments un par un dans un formalisme de ton cru (comme le CSV d'excel). De l'autre coté tu refais l'opération inverse. C'est compatible multi-os et y compris pour les zones allouées puisque tu les traites aussi

    Les autres techniques seront des variations de ces deux techniques de base...

    Citation Envoyé par Zulhuky Voir le message
    Ca n'est pas dit explicitement que l'on doit faire une structure pour les informations du fichier, mais ca me semblait évident.
    Exact - Tu devrais d'ailleurs aller voir le "struct stat"...

    Citation Envoyé par Zulhuky Voir le message
    Mais ca sera bien plus galère pour l'extraction
    Pas forcément. Tu connais la taille du fichier (enfin j'espère) donc tu boucles jusqu'à avoir lu "n=taille" octets...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. Ouvrir un fichier en mode binaire.
    Par _christophe_ dans le forum Général Python
    Réponses: 20
    Dernier message: 14/05/2008, 06h28
  2. Ecriture dans un fichier en mode binaire
    Par greg1517 dans le forum C
    Réponses: 14
    Dernier message: 11/02/2008, 17h35
  3. ouverture/lecture/ecriture dans un fichier en mode binaire
    Par dirty_boy dans le forum Débuter
    Réponses: 2
    Dernier message: 15/03/2006, 08h38
  4. [9.2.0.4 - forms 6i] Lire un fichier en mode RAW
    Par gaultier dans le forum Oracle
    Réponses: 3
    Dernier message: 30/01/2006, 11h11
  5. Réponses: 4
    Dernier message: 04/11/2005, 09h04

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