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 :

write(), bytes inversés et supplémentaires


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Juin 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2011
    Messages : 6
    Par défaut write(), bytes inversés et supplémentaires
    Bonjour à tous (et toutes),

    Voila mon problème :

    Je voudrais écrire cette structure

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct{
      int i;
      unsigned char vote ;
    } enr;
    dans un fichier de type binaire. Pour faire simple, j'ai un tableau d'un milliard de bits, codé sur 125 millions bytes. Je voudrais sauver seulement les bytes non null (car il y en a que maximum 10 millions qui sont non null), puisque sauver des 0 c'est bien, mais ça prend de la place et c'est null

    J'ai eu l'idée de faire une structure qui prend l'indice dans le tableau, suivit de la valeur, et d'écrire cette structure dans un fichier.

    Voici le code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        int fd = 0;
        char* path = malloc (21);
        path = strcpy(path, getNameBKP());
     
        if((fd = open (path, O_CREAT|O_WRONLY, 00666 )) < 0)
            exit(-1);
     
        int i = -1;
        while(++i < NBVOTER) //NBVOTER = 1 000 000 000 /8 = 125 000 000
            if(vote[i]){
                enr en = {i, vote[i]};
                write(fd, &en, sizeof(en));
            }
        close(fd);
    Le résultat que j'obtiens est assez bizarre.
    Si dans mon tableau je n'ai (en hexa) que 04 à l'indice 3, dans mon fichier j'ai (en hexa) : 03 00 00 00 04 00 00 00

    Si quelqu'un à une idée du pourquoi les bits de poids faible et fort sont inversés, et du comment les remettre dans le bon sens, ou du pourquoi un unsigned char passe sur 32 bits, ce serait chouette.


    Merci d'avance

    Ah oui, petits détails qui éviteront des posts inutiles, les chiffres 10E9 et 10E7 sont fixés, et je ne peux pas les changer, et j'ai pas envie de me retrouver avec des fichiers de 125Mo à chaque fois que je sauve mon tableau.

  2. #2
    Inactif  
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 123
    Par défaut pragma
    Windows ou Linux ?
    ajoute une pragma
    Vois du côté de :pragma

  3. #3
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 971
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 971
    Par défaut
    Jai,

    olivieram a raison : c'est encodé en Little Endian, comme tous les systèmes à base x86 ou x64.

  4. #4
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Juin 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2011
    Messages : 6
    Par défaut
    Citation Envoyé par olivieram Voir le message
    Windows ou Linux ?
    ajoute une pragma
    Vois du côté de :pragma
    C'est sous linux (ubuntu 10.04).

    Merci, je regarde ce qu'est une pragma.


    edit:

    Citation Envoyé par droggo Voir le message
    Jai,

    olivieram a raison : c'est encodé en Little Endian, comme tous les systèmes à base x86 ou x64.
    OK, je m'y connais pas trop en type de codages. Il y a plusieurs manières d'encoder dans un fichier?

  5. #5
    Inactif  
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 123
    Par défaut encoder dans un fichier
    Non, il n'y a pas plusieurs manières d'écrire dans un fichier.
    Cela s'appelle en fait des "facilities" parce que le fonctionnement de la librairie fournit, en standard, la possibilité d'écrire dans un format d'encodage particulier. Il s'agit le plus souvent de UTF-8, ISO ou Unicode pour du texte.

  6. #6
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Juin 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2011
    Messages : 6
    Par défaut
    Pour les bytes en trop, j'ai trouvé une solution dégueulasse mais qui marche, au lieu d'écrire ma structure en une fois, j'écris d'abord le int, puis le unsigned char.

    Apparemment, sizeof(enr) = 8, sizeof(enr.i) = 4 et sizeof(enr.vote) = 1, d'ou 4 +1 => 8
    Un petit truc de fou qui sort de nulle part, et qui alimente les forums.


    Citation Envoyé par olivieram Voir le message
    Non, il n'y a pas plusieurs manières d'écrire dans un fichier.
    Cela s'appelle en fait des "facilities" parce que le fonctionnement de la librairie fournit, en standard, la possibilité d'écrire dans un format d'encodage particulier. Il s'agit le plus souvent de UTF-8, ISO ou Unicode pour du texte.
    Sinon je cherche toujours pour écrire de hb vers lb, ou lire de lb vers hb. Si tu as une idée de la ligne qu'il faut taper pour changer le format d'encodage (si vraiment ça change quelque chose).
    Merci d'avance.

    EDIT:
    Je viens de réessayer de lire le fichier, et apparemment ça ne pose pas de problème que ce soit écrit à l'envers, il me lis bien tous les éléments. Donc c'était juste un problème à cause de la structure, avec des bytes en trop lors de l'écriture.

    Un grand Merci à ceux qui ont répondu au post!

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    C'est pour cette raison qu'il est déconseillé d'écrire directement une structure dans un fichier binaire. Tu devrais en sérialiser le contenu toi-même pour l'écriture:
    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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    void write_uint(FILE* pfOut, unsigned int val)
    {
    	const unsigned int BITS_RIGHT = (sizeof(int)-1) * CHAR_BIT;
    	const unsigned int LSBITS = ((unsigned int)-1) >> BITS_RIGHT;
    	for(int i=0 ; i<sizeof(int) ; i++)
    	{
    		fputc((val >> BITS_RIGHT) & LSBITS, pfOut);
    		val <<= CHAR_BIT;
    	}
    }
    unsigned int read_uint(FILE* pfIn)
    {
    	unsigned int val = 0;
    	for(int i=0 ; i<sizeof(int) ; i++)
    	{
    		val <<= CHAR_BIT;
    		val |= fgetc(pfIn);
    	}
    }
     
    void write_int(FILE* pfOut, int val)
    { write_uint(pfOut, (unsigned int)val; }
     
    int read_int(FILE* pfIn)
    { return (int)read_uint(pfIn); }
     
    void write_struct_enr(FILE* pfOut, enr const *pcObj)
    {
    	write_int(pfOut, pcObj->i);
    	fputc(pcObj->vote, pfOut);
    }
    void read_struct_enr(FILE* pfIn, enr *pObj)
    {
    	pObj->i = read_int(pfIn);
    	pObj->vote = fgetc(pfIn);
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Inactif  
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 123
    Par défaut
    Citation Envoyé par tompus Voir le message
    Sinon je cherche toujours pour écrire de hb vers lb, ou lire de lb vers hb. Si tu as une idée de la ligne qu'il faut taper pour changer le format d'encodage (si vraiment ça change quelque chose).
    Merci d'avance.
    hb signifie high-byte et lb signifie low-byte ?

  9. #9
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Juin 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2011
    Messages : 6
    Par défaut
    Citation Envoyé par olivieram Voir le message
    hb signifie high-byte et lb signifie low-byte ?
    oui, normalement c'est lsb (Least Significant Bit), et msb (Most Significant Bit), merci de la correction.

  10. #10
    Expert confirmé
    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
    Par défaut
    oui, normalement c'est lsb (Least Significant Bit), et msb (Most Significant Bit), merci de la correction.
    Non, la question ici concerne l'ordre d'écriture des bytes pas des bits. L'ordre des bits dans un byte n'est pas concerné.

  11. #11
    Inactif  
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 123
    Par défaut
    @tompus
    a vous de choisir, c'est des bytes ou des bits ?

  12. #12
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Juin 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2011
    Messages : 6
    Par défaut
    Citation Envoyé par diogene Voir le message
    Non, la question ici concerne l'ordre d'écriture des bytes pas des bits. L'ordre des bits dans un byte n'est pas concerné.
    Normalement j'écris toujours de msb a gauche, et lsb a droite, sauf que write les écris de lsb vers msb. Vu que read lis de lsb vers msb, ca perturbe ma petite nature quand j'ouvre le fichier en hexa, mais ca fonctionne.

    Par exemple pour écrire 5 (en int), j'ai toujours écris 00000000 00000000 00000000 00000101, et dans le fichier il écris 00000101 00...00 .

    Donc je crois que j'ai toujours mal écris, ou que pour des questions existentielles, on a décidé que write et read allaient écrire/lire des bytes dans l'autre sens.

  13. #13
    Expert confirmé
    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
    Par défaut
    Tu écris (comme tout le monde) en mettant MSB(it) à gauche et LSB(it) à droite.
    La fonction write(), pour son compte, écrit une zone mémoire et le résultat est l'image de cette zone mémoire. Or il existe plusieurs systèmes (boutisme) pour coder en mémoire un nombre tenant sur plus d'un byte selon la machine (le processeur) utilisée. Les deux plus courants sont
    - le boutisme BigEndian où le premier byte est celui qui contient les bits les plus significatifs et le dernier byte contient les bits les moins significatifs
    - le boutisme LittleEndian où le premier byte est celui qui contient les bits les moins significatifs et le dernier byte contient les bits les plus significatifs.
    Il y a donc entre les deux cas inversion des bytes.

    Ta machine est donc dans le deuxième cas.

    Naturellement, le read() procède de la même façon. Alors, si le write() et le read() sont faits sur une même machine (ou deux machines de même boutisme), le boutisme n'a pas d'incidence sur le fonctionnement.

  14. #14
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Juin 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2011
    Messages : 6
    Par défaut
    Ok, merci diogene

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

Discussions similaires

  1. Port sériel et méthode Write(byte[],offset,length)
    Par TheCaribouX dans le forum C#
    Réponses: 6
    Dernier message: 02/06/2008, 17h10
  2. [C#] Conversion d'un byte[] en byte *
    Par karsh dans le forum Windows Forms
    Réponses: 6
    Dernier message: 08/12/2004, 10h53
  3. [STRUTS] bean:write
    Par lfournial dans le forum Struts 1
    Réponses: 3
    Dernier message: 30/01/2004, 09h58
  4. transtyper ^dword en ^byte ?
    Par - Robby - dans le forum Langage
    Réponses: 3
    Dernier message: 28/10/2003, 00h58
  5. write() dans une socket.. unix
    Par slack dans le forum Réseau
    Réponses: 5
    Dernier message: 18/12/2002, 20h42

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