2016-04-15 8 views
0

Ich versuche, eine lange (signiert, 4 Bytes) aus einer Binärdatei in C++ zu lesen. Mein Hauptanliegen sind: Portabilität (Longs sind unterschiedliche Größen auf verschiedenen Plattformen), wenn Sie aus Binärdateien mit std :: ifstream lesen, kehrt es die Byte-Reihenfolge (auf die Endlichkeit meiner Maschine).Lange Lesevorgänge von der Datei umkehren?

Ich verstehe für Datentypen wie unsigned int, können Sie einfach bitweise Operatoren und verschieben und UND jedes Byte, um die Byte-Reihenfolge nach dem Lesen aus einer Datei umzukehren.

Ich bin nur nicht sicher, was ich dafür tun würde: Zeit meinen Code ad absurdum Wert geben:

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

Ich bin nicht sicher, wie ich Portabilität erreichen kann (ich lese etwas über Gewerkschaften und Char *) und auch umgekehrt unterzeichnet lange es liest.

Danke.

+1

Sie würden es nur umkehren, wenn es nicht die Endian auf Ihrem System entspricht. Sie sollten Datentypen mit bestimmten Größen verwenden, die in '' definiert sind. Lesen Sie in eine Zeichenfolge und konstruieren Sie den Wert dann mithilfe von Bitverschiebungen und Maskierung. Dann wird Ihr Code unabhängig von der Endianz auf Ihrem System sein. – paddy

Antwort

0

Anstatt long zu verwenden, verwenden Sie int32_t von <stdint.h>, um direkt eine 32-Bit-Ganzzahl anzugeben. (oder uint32_t für unsigned).

Verwenden Sie htonl and ntohl entsprechend, um zu/von Netzwerk-Byte-Reihenfolge zu erhalten.

Besser:

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

Ich würde vorschlagen, dass Sie Funktionen wie Htonl, Htnons, Ntohl und Ntohs verwenden. Diese werden in der Netzwerkprogrammierung verwendet, um das gleiche Ziel zu erreichen: Portabilität und Unabhängigkeit von Endianess.

0

Da Cross-Plattform-Unterstützung für Sie wichtig ist, würde ich empfehlen, cstdint zu verwenden, um die Größe Ihrer Typen anzugeben. Sie können beispielsweise int32_t x sagen und wissen, dass Sie 32 Datenbits erhalten.

In Bezug auf die Endianess der Daten würde ich empfehlen, auf ein Format zu standardisieren (zB alle Daten sind im Little-Endian-Format geschrieben) und wickeln Ihre I/O-Operationen in einer Klasse und damit zum Lesen/Schreiben der Daten. Dann mit einem #define entscheiden, wie die Daten zu lesen:

#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 

Alternativ Sie mit so etwas wie Google Protobuf aussehen könnte, die Pflege aller Codierung Fragen für Sie brauchen.