2011-07-26 8 views
3

Je cette question, je ne sais pas si l'on attend, voici la chose:C++ Lecture octets Problème

Je suis en train de charger octets d'un fichier à une structure comme celle-ci:

struct 
{ 
    char 
    char 
    char 
    char 
    unsigned int 
} 

mais le problème est lorsque l'entier non signé est rempli, il semble que dans le flux de lecture, les octets sont échangés, ex Si le fichier contient 0x45080000, l'entier non signé aura 0x84500000, ce qui est faux.

Cela peut être "résolu" si je change l'int non signé pour un BYTE [4], mais ce n'est pas ce que je veux. Voici le code que j'utiliser pour lire à partir du fichier:

fopen_s(&mFile, "myFile.ext", "rb"); 

if(mFile == NULL) print(" **** E R R O R ! **** "); 
else 
{ 
    if(fread(&myStruct, sizeof(MY_Struct), 1, myFile) != 1) 
    { 
     print(" **** E R R O R ! **** "); 
     return 0; 
    } 
} 

Est-ce un comportement attendu ou ce que je fais mal?

salutations

+7

L'endianisme vous mordra dans le cul. –

+0

Grands messages d'erreur! Je noterai ceci pour moi-même. – RocketR

+0

Je ne sais pas si c'est un problème d'endianness parce que je suis en train de lire les octets comme ils sont dans le fichier stocké, un par un, donc l'endianness ne devrait pas affecter, je pense –

Répondre

1

Soit sérialiser/désérialiser chaque champ indépendamment (normes conforme) ou ...

utiliser une plate-forme option spécifique:

#pragma pack(push,1) 
struct foo { 
    // ... 
}; 
#pragma pack(pop) 

Ceci aligne toutes les variables foo à 1 octet alignement, donc ça ne marchera pas pour un booléen.

Si vous avez l'intention d'être multiplate-forme, vous devrez tester l'enfer pour des problèmes d'endianess et de support de pragma.

+0

ouais, ce sera multi-plateforme, mais je ne peux pas sérialiser chaque champ, parce que si j'ai un gros fichier, et j'ai besoin de saisir quelques informations, ou vous pensez que la meilleure solution est de lire octet par octet? –

+0

@ user864094 Il est difficile de répondre à cette question sans connaître la structure du fichier. Vous devez probablement décrire ce que vous essayez de faire plus. –

+0

est un fichier, qui stocke des informations sur les cadres et modules, comme un éditeur de sprite, ce fichier a un en-tête avec les 4 premiers octets indiquant un nom, un autre octet indiquant si un module ou une animation ou un cadre, puis int non signé qui est une taille à lire info, mais, le problème vient ici, car comme je l'ai dit, si la taille est 0x45080000, le programme lui-même mis le 08 au début, mais cela ne se produit pas lorsque je lis octet par octet quand je change les types –

3

Comme vous l'avez découvert, la sérialisation portable peut être pénible. Au lieu d'écrire et de lire la structure, vous devez sérialiser chaque attribut individuellement dans un format normalisé (l'ordre des octets réseau est courant). Ensuite, lorsque vous désérialisez les octets, revenez correctement.

+0

ups, alors je pense que je vais préparer toute la douleur = ( –

0

vous avez probablement besoin de prendre en compte big/little endian. essayez le premier. comme ceci:

#define BIG_ENDIAN 
//#define LITTLE_ENDIAN 
... 
#ifdef BIG_ENDIAN 

inline void writeMem32(uint8* buf, uint32 val) 
{ 
    buf[0] = static_cast<uint8>(val >> 24); 
    buf[1] = static_cast<uint8>(val >> 16); 
    buf[2] = static_cast<uint8>(val >> 8); 
    buf[3] = static_cast<uint8>(val >> 0); 
} 

inline uint32 readMem32(const uint8* buf) 
{ 
    return (((*(buf+0)) << 24) | ((*(buf+1)) << 16) | ((*(buf+2)) << 8) | (*(buf+3))); 
} 

#endif // BIG_ENDIAN 

si vous êtes peu endian l'ordre des octets est bien sûr différent :)

+0

peut-être est le problème, si le fichier est écrit en petit boutiste, les octets ne sont pas lus dans le même ordre –

+3

Il y a les fonctions standard 'hton' /' ntoh' Ne pas réinventer la roue – RocketR

+0

@RocketR: Je suis d'accord. J'ai trouvé qu'il est parfois utile de réinventer juste pour avoir une meilleure compréhension de ce qui se passe vraiment ... c'est du moins ce qui est vrai pour moi-même :) – oliver

1

Juste pour ajouter un peu de cerise sur le gâteau!

Vous devez également gérer les problèmes 32 bits et 64 bits.

Un très bon fichier include est stdint.h (C99). Il définit les types avec une taille spécifique de sorte que vous obtenez moins de problèmes lors de la commutation de la largeur du mot.

Questions connexes