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 :

fwrite fread en mode binaire


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut fwrite fread en mode binaire
    Bonjour,

    Je souhaite réaliser une simple analyse de fréquence sur un fichier quelquonque.
    Pour cela je suppose qu'un élément sera interprété en tant qu'un unsigned int soit 4 octets dans mon environnement (windows 7).
    Partant de là, j'ai donc 2^32 possibilités de valeurs. Par conséquent, je crée un fichier de 2^32*4 octets = 16Go pour stocker la fréquence d'apparition des mots binaire. La limite étant qu'un mot binaire ne devrait pas apparaître plus de 2^32-1 fois dans un fichier donnée.

    Je parcours donc le fichier à analyser 4 octets par 4 octets, chaque 4 octets est alors interprété comme un unsigned int. Je me déplace dans le fichier de stockage à l'offset correspondant à la valeur récupérée et j'incrémente de 1 la fréquence.

    Sauf que dans mon code, la taille du fichier augmente et dépasse les 16Go, ce qui revéle que je vais écrire plus loins que la limite "autorisée".

    Ceci est la ligne qui positionne le curseur dans le fichier avant écriture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fseek(f_dst, buffer_src*sizeof(unsigned int), SEEK_SET);
    J'en déduis donc qu'au moins cette ligne est incorrecte conformément à ce que je souhaite faire.
    Je n'arrive pas à analyser mon erreur, est ce qu'un oeil expert pourrait m'aiguiller ?

    Merci d'avance pour votre aide.

    Voici le code de la fonction.

    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
    FILE *binary_analyse( const char *path )
    {
        FILE *f_dst = NULL;
        if (path)
        {
            FILE *f_dst = NULL;
            FILE *f_src = NULL;
            if ( (f_dst = file_open("D:\\table", "wb")) )
            {
                /* On travaille avec des unsigned int (4 octets soit 4294967296 valeurs différentes définissant une plage allant de 0 à 4294967295 */
                /* Cette boucle génére un fichier de 4294967296 "cases" de 4 octets chacunes */
                /* Ce fichier a pour but de stocker la fréquence d'apparition d'une valeur de cette plage à l'offset équivalent */
     
                /* On génère le fichier de 16 Go en l'initialisant avec des 0 */
                t_uint64 i=0;
                unsigned int j = 0;
                for ( i=0 ; i < 4294967296 ; i++)
                    fwrite(&j, sizeof(unsigned int), 1, f_dst);
     
                file_close(f_dst);
            }
            else printf("\n%s", strerror(errno));
     
            if ( (f_src = file_open(path, "rb")) && (f_dst = file_open("D:\\table", "ab")) )
            {
                t_uint64 read_byte, written_byte, total_written_byte=0;
                unsigned int buffer_src = 0;
                unsigned int buffer_dst = 0;
                unsigned int x = 0;
     
                /* Parcourir le fichier à analyser 4 octets par 4 octets, on récupère la valeur décimale équivalente de type unsigned int dans buffer_src */
                while (0<(read_byte=fread(&buffer_src, sizeof(unsigned int), 1, f_src)))
                {
     
                    /* Se Positionner dans le fichier de 16Go à l'offset de la valeur récupérée dans buffer_src */
                    fseek(f_dst, buffer_src*sizeof(unsigned int), SEEK_SET);
                    /* Lire cette valeur à l'offset trouvé*/
                    fread(&buffer_dst, sizeof(unsigned int), 1, f_dst);
                    /* Incrémenter de 1 la fréquence d'apparition de cette valeur */
                    x=buffer_dst+1;
                    /* Modifier cette valeur dans le fichier de 16 Go  */
                    fwrite(&x, sizeof(unsigned int), 1, f_dst);
     
                    total_written_byte+=read_byte*sizeof(unsigned int);
                }
                total_written_byte+=read_byte*sizeof(unsigned int);
                file_close(f_src);
                file_close(f_dst);
     
                t_uint64 f_src_size = file_length(path);
     
                if ( total_written_byte != f_src_size )
                    printf("\n Erreur taille fichier : %I64u %I64u", f_src_size, total_written_byte );
            }
        }
        return f_dst;
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
                    /* Se Positionner dans le fichier de 16Go à l'offset de la valeur récupérée dans buffer_src */
                    fseek(f_dst, buffer_src*sizeof(unsigned int), SEEK_SET);
                    /* Lire cette valeur à l'offset trouvé*/
                    fread(&buffer_dst, sizeof(unsigned int), 1, f_dst);
                    /* Incrémenter de 1 la fréquence d'apparition de cette valeur */
                    x=buffer_dst+1;
                    /* Modifier cette valeur dans le fichier de 16 Go  */
                    fwrite(&x, sizeof(unsigned int), 1, f_dst);
    Bonjour

    Quand tu lis f_dst, tu déplaces alors le pointeur de fichier de ce qui a été lu. Ensuite, quand tu réécris ta valeur modifiée, tu la réécris sur l'int suivant.
    Si par exemple ton fichier avait "axx" et que tu te focalises sur le "a" pour le faire passer à "b", alors ton code produirait "abx" et non "bxx".

    Te faut refaire un fseek avant de réécrire (d'ailleurs c'est obligatoire quand on fait de la lecture+écriture => toute lecture suivie d'écriture doit faire précéder l'écriture par un fseek() (même si on est déjà à la bonne position) et toute écriture suivie de lecture doit faire précéder la lecture soit d'un fseek(), soit d'un fflush())

    PS: Utilise plutôt le nombre 0x100000000 au lieu de 4294967296...
    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]

  3. #3
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    Ah ok, autant de choses dont je n'avais pas conscience effectivement. Donc merci pour ta réponse.
    Quelle est l'avantage de mettre la valeur hexa plutôt que de mettre la valeur décimale ?

    Si j'ai bien compris ce que tu m'as expliqué ici, c'est que je devrais donc ajouter la ligne suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fseek(f_dst, (ftell(f_dst)-1)*sizeof(unsigned int), SEEK_SET);
    après cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fread(&buffer_dst, sizeof(unsigned int), 1, f_dst);
    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
    59
    FILE *binary_analyse( const char *path )
    {
        FILE *f_dst = NULL;
        if (path)
        {
            FILE *f_dst = NULL;
            FILE *f_src = NULL;
            if ( (f_dst = file_open("D:\\table", "wb")) )
            {
                /* On travaille avec des unsigned int (4 octets soit 4294967296 valeurs différentes définissant une plage allant de 0 à 4294967295 */
                /* Cette boucle génére un fichier de 4294967296 "cases" de 4 octets chacunes */
                /* Ce fichier a pour but de stocker la fréquence d'apparition d'une valeur de cette plage à l'offset équivalent */
     
                /* On génère le fichier de 16 Go en l'initialisant avec des 0 */
                t_uint64 i=0;
                unsigned int j = 0;
                for ( i=0 ; i < 4294967296 ; i++)
                    fwrite(&j, sizeof(unsigned int), 1, f_dst);
     
                file_close(f_dst);
            }
            else printf("\n%s", strerror(errno));
     
            if ( (f_src = file_open(path, "rb")) && (f_dst = file_open("D:\\table", "ab")) )
            {
                t_uint64 read_byte, written_byte, total_written_byte=0;
                unsigned int buffer_src = 0;
                unsigned int buffer_dst = 0;
                unsigned int x = 0;
     
                /* Parcourir le fichier à analyser 4 octets par 4 octets, on récupère la valeur décimale équivalente de type unsigned int dans buffer_src */
                while (0<(read_byte=fread(&buffer_src, sizeof(unsigned int), 1, f_src)))
                {
     
                    /* Se Positionner dans le fichier de 16Go à l'offset de la valeur récupérée dans buffer_src */
                    fseek(f_dst, buffer_src*sizeof(unsigned int), SEEK_SET);
                    /* Lire cette valeur à l'offset trouvé*/
                    fread(&buffer_dst, sizeof(unsigned int), 1, f_dst);
                    /* Incrémenter de 1 la fréquence d'apparition de cette valeur */
                    x=buffer_dst+1;
                    /* Repositionner le curseur à l'offset précédent après lecture */
                    fseek(f_dst, (ftell(f_dst)-1)*sizeof(unsigned int), SEEK_SET);
                    /* Modifier cette valeur dans le fichier de 16 Go  */
                    fwrite(&x, sizeof(unsigned int), 1, f_dst);
     
                    total_written_byte+=read_byte*sizeof(unsigned int);
                }
                total_written_byte+=read_byte*sizeof(unsigned int);
                file_close(f_src);
                file_close(f_dst);
     
                t_uint64 f_src_size = file_length(path);
     
                if ( total_written_byte != f_src_size )
                    printf("\n Erreur taille fichier : %I64u %I64u", f_src_size, total_written_byte );
            }
        }
        return f_dst;
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Quelle est l'avantage de mettre la valeur hexa plutôt que de mettre la valeur décimale ?
    Je sais pas. Ca ne te semble pas plus élégant, plus parlant et plus facile à retenir ce beau nombre rond plutôt que ce 4294967296 que personne ne connait par coeur ce qui oblige quiconque veut te relire à prendre sa calculatrice et à calculer 2**32???...

    Citation Envoyé par darkwall_37 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fseek(f_dst, (ftell(f_dst)-1)*sizeof(unsigned int), SEEK_SET);
    Ben oui mais non. Déjà tu aurais pu penser à faire "-1" avec SEEK_CUR mais sinon tu as déjà la bonne position avec "buffer_src" !!! Qu'est-ce que tu te compliques la vie avec ce ftell()-1 ???
    Dans le même genre de remarque, ta variable "x" ne sert à rien...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
                    // Se Positionner dans le fichier de 16Go à l'offset de la valeur récupérée dans buffer_src
                    fseek(f_dst, buffer_src*sizeof(unsigned int), SEEK_SET);
     
                    // Lire cette valeur à l'offset trouvé
                    fread(&buffer_dst, sizeof(unsigned int), 1, f_dst);
     
                    // Incrémenter de 1 la fréquence d'apparition de cette valeur
                    buffer_dst++;
     
                    // Se repositionner dans le fichier de 16Go à l'offset de la valeur récupérée dans buffer_src
                    fseek(f_dst, buffer_src*sizeof(unsigned int), SEEK_SET);   // fseek(f_dst, -sizeof(unsigned int), SEEK_CUR);
     
                    // Modifier cette valeur dans le fichier de 16 Go
                    fwrite(&buffer_dst, sizeof(unsigned int), 1, f_dst);
    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]

  5. #5
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    Oui en effet c'est probablement plus élégant.
    La variable x ne sert plus à rien, on est d'accord car à la base, il y avait des choses en plus et effectivement je ne l'ai pas modifié.
    Et pour le reste, oui aussi.

    Du coup, avant de rajouter cette ligne, le fichier passait de 16Go à 28 Go après analyse
    Maintenant il passe de 16 à 16,2Go pour le même fichier analysé bien ententdu. J'imagine qu'il y a donc encore un problème.

    D'ailleurs, comment peut-on expliquer que le programme puisse écrire au dela des 16Go étant donné que la valeur max récupérable qui indique la posistion où écrire est stockée dans un unsigned int et qui par conséquent doit avoir pour valeur maximale 0x100000000-1 à savoir le dernier 4-octet du fichier de 16 Go?
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 685
    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 685
    Points : 30 974
    Points
    30 974
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Maintenant il passe de 16 à 16,2Go pour le même fichier analysé bien ententdu. J'imagine qu'il y a donc encore un problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( (f_src = file_open(path, "rb")) && (f_dst = file_open("D:\\table", "ab")) )
    Ben oui, tu as ouvert ton fichier en mode "append" !!!!
    En mode "append", toute écriture se fait toujours à la fin même si fseek().
    Te faut l'ouvrir en mode "r+b"...

    Et sinon tu peux accélérer la création du fichier zéro en utilisant un bloc de travail écrit en une fois. C'est en effet plus rapide d'appeler une fois fwrite() en lui passant "n" int qu'appeler n fois fwrite() en lui donnant un int...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define BUFFER		(0x10000)
    int tampon[BUFFER];
    memset(tampon,0, BUFFER);
    for ( i=0 ; i < 0x100000000 ; i+=BUFFER)
    	fwrite(tampon, sizeof(unsigned int), BUFFER, f_dst);
    Ensuite tu fais varier BUFFER selon la mémoire de ta machine...
    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]

  7. #7
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    ++++++++++++++++++++++++++++++++++++++++++++++++1

    Merci, je teste tout ça.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 07/11/2010, 13h04
  2. 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
  3. Réponses: 4
    Dernier message: 04/11/2005, 09h04
  4. Accéder au contenu d'un fichier via une URL en mode binaire
    Par sbelli dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 11/10/2005, 10h25
  5. Réponses: 5
    Dernier message: 11/12/2002, 12h31

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