2016-04-15 1 views
0

J'essaye de lire un long (signé, 4 octets) d'un fichier binaire en C++. Mes principales préoccupations sont les suivantes: la portabilité (les longueurs sont de tailles différentes sur des plates-formes différentes), lorsque vous lisez des fichiers binaires w/std :: ifstream, elle inverse l'ordre des octets (à l'endianness de ma machine). Je comprends pour les types de données comme unsigned int, vous pouvez simplement utiliser les opérateurs bit et shift et AND chaque octet pour inverser l'ordre des octets après avoir été lu à partir d'un fichier.Inverser la lecture longue du fichier?

Je ne suis pas sûr de ce que je ferais pour cela: Actuellement mon code donnera une valeur non-sens:

long value; 
in.seekg(0x3c); 
in.read(reinterpret_cast<char*>(&value), sizeof(long)); 

Je ne sais pas comment je peux obtenir la portabilité (je l'ai lu quelque chose unions et char *) et aussi inverser le long signé qu'il lit.

Merci.

+1

Vous ne le renverser si elle ne correspond pas au boutisme sur votre système. Vous devez utiliser des types de données avec des tailles spécifiques définies dans ''. Lisez dans une chaîne, puis construisez la valeur en utilisant les changements de bits et le masquage. Votre code sera alors indépendant de l'endianness sur votre système. – paddy

Répondre

0

Plutôt que d'utiliser long, utilisez int32_t de <stdint.h> pour spécifier directement un entier de 32 bits. (ou uint32_t pour non signé).

Utilisez htonl and ntohl comme il se doit pour accéder à l'ordre des octets du réseau.

Mieux:

int32_t value; 
in.seekg(0x3c); 
in.read(reinterpret_cast<char*>(&value), sizeof(value)); 
value = ntohl(value); // convert from big endian to native endian 
0

Je vous suggère d'utiliser des fonctions comme htonl, htnons, ntohl et ntohs. Ils sont utilisés dans la programmation réseau pour atteindre le même objectif: la portabilité et l'indépendance de l'endianness.

0

Étant donné que le support multiplateforme est important pour vous, je vous recommande d'utiliser cstdint pour spécifier la taille de vos types. Vous serez en mesure de dire int32_t x (par exemple) et vous savez que vous obtenez 32 bits de données. En ce qui concerne l'endianness des données je recommanderais de standardiser sur un format (par exemple toutes les données sont écrites dans le petit format d'endian) et encapsulez vos opérations d'E/S dans une classe et employez pour lire/écrire les données. Ensuite, utilisez un #define pour décider comment lire les données:

#ifdef BIG_ENDIAN 
    // Read the data that is in little endian format and convert 

#else 
    // We're in little endian mode so no need to convert data 
#endif 

Sinon, vous pouvez envisager d'utiliser quelque chose comme Google Protobuf qui prendra soin de tous les problèmes de codage pour vous.