2016-06-14 6 views
3

Ich habe ich Datei möchte ich in C++ lesen. Das erste, was ich lesen und überprüfen muss, ist die magische Nummer der Datei. In meinem Fall ist es der Hex-Wert: 0xABCDEF00C++ lesen und vergleichen magische Zahl aus Datei

ich die Nummer auf diese Weise lesen und vergleichen:

ifstream input ("C:/Desktop/myfile", ios::binary); 
if (input.is_open()) { 
input.seekg(0, ios::beg); 
unsigned char magic[4] = {0}; 
input.read((char*)magic, sizeof(magic)); 

if(magic[0] == 0xAB && 
    magic[1] == 0xCD && 
    magic[2] == 0xEF && 
    magic[3] == 0x00) { 
    cout << "It's my File!" << endl; 
} else { 
    cout << "Unknown File!" << endl; 
} 
} 

Das funktioniert sehr gut, aber gibt es eine Möglichkeit, die gesamte Lese char [] zu vergleichen - Array sofort? Wie auf diese Weise:

unsigned int magicNumber = 0xABCDEF00; 
... same code for reading file as above ... 
Instead of checking each Array-Entry a way like this: 

if(magic == magicNumber) { 
    do something ... 
} 

Wäre schön zu wissen, ob es eine solche Art und Weise ist - wenn nicht vielen Dank für Teeling mir, dass es keine solche Art und Weise :)

+3

Sie könnten memcpy verwenden, um den Inhalt des char-Arrays in ein unsigned int zu kopieren. 'memcpy (& anZahlInt, magic, sizeof (unsigned int));' – Christoph

+0

Ist eine magische Zahl im Bereich von 'long'? Dann betrachte 'std :: stol' oder vertraut (' stoi' für 'int',' stoll' für 'long long', füge' u' vor 'i' /' l'/'ll' hinzu für unsigned) ... –

+1

Nicht in Binärdatei arbeiten, @LapshinDmitry – user4581301

Antwort

2

gute alte memcmp könnte hier helfen. Sobald Sie die unsigned char magic[4] gelesen haben, können Sie den Vergleich so einfach wie tun:

const unsigned char magicref[4] = {0xAB, 0xCD, 0xEF, 0} 
if (memcmp(magic, magicref, sizeof(magic)) == 0) { 
    // do something ... 
} 

Dieses endianness unabhängige ist.

Wenn Sie wissen, was Sie Plattform, die Sie für die magische Zahl geben und kümmern sich nicht um die Portabilität auf andere Plattformen, direkt alles wie uint32_t verarbeiten kann:

uint32_t magic, refmagic = 0xABCDEF00; // big endian here... 
input.read(reinterpret_cast<char *>(&magic), sizeof(magic)); // directly load bytes into uint32_t 
if (magic == refmagic) { 
    //do something... 
} 

Diese auf verschiedenen Plattformen nicht tragbar ist, aber kann in einfachen Fällen verwendet werden, ein Kommentar in Fett rot blinkenden Schriftart mit der Sprichwort Achtung: nur auf Big-Endian-System

+0

Der erste Teil wäre die beste Lösung für mich, denke ich. Sehr gut, dass es endianess unabhängig ist. Aber das 'const char magicref [4] = {0xAB, 0xCD, 0xEF, 0}' sollte sein 'const vorzeichenloses Zeichen magicref [4] = {0xAB, 0xCD, 0xEF, 0} '. Wenn nicht, bekomme ich einige Compilerwarnungen wie: Warnung: Die Umwandlung von '237' von 'int' auf 'const char' innerhalb von – Opa114

+1

einzuschränken Um perfekt zu sein @ Opa114 sollte es eigentlich stattdessen uint8_t sein, da dies keine semantischen Zeichen sind. – olivecoder

+0

@olivecoder danke für den Hinweis, ich versuche'Uint8_t' anstelle von 'unsigend char' – Opa114

0

Wenn Sie die Byte-Reihenfolge Ihrer Plattform wissen, Sie können dazu eine uint32_t Variable verwenden.

Für ein Little-Endian-System verwenden:

unit32_t number; 
input.read(reinpterpret_cast<char*>(&number), 4); 
if (number == 0x00EFCDAB) 
{ 
    cout << "It's my File!" << endl; 
} 

Für ein Big-Endian-System verwenden:

unit32_t number; 
input.read(reinpterpret_cast<char*>(&number), 4); 
if (number == 0xABCDEF00) 
{ 
    cout << "It's my File!" << endl; 
} 
1

Es gibt bereits sehr gute Antworten hier! Für die Aufzeichnungen, hier eine Variante equal() der Standard <algorithm> Bibliothek:

unsigned char magic[4] = {0}; 
input.read((char*)magic, sizeof(magic)); 

const unsigned char code[4] = { 0xab, 0xcd, 0xef, 0x00 }; 
if(equal(code, code+sizeof(code), magic)) 
    cout << "It's my File!" << endl; 
else 
    cout << "Unknown File!" << endl; 

Es ist sehr ähnlich wie die memcmp()-Version, aber es funktioniert mit jedem Behälter, nicht nur Arrays von char.

Online demo

2

Sie tun können:

union magic_t { 
    uint8_t bytes[4]; 
    uint32_t number; 
}; 

dann, wie Sie ursprünglich wollten:

magic_t my_magic = {0xAB, 0xCD, 0xEF, 0}; 
magic_t file_magic; 
input.read((char *) file_magic.bytes, sizeof(file_magic)); 
if (file_magic.number == my_magic.number)... 

und Sie gar nicht über Endianess zu kümmern brauchen.

Abhängig von der Endianness-Nummer kann unterschiedlich sein, aber das ist überhaupt egal, das wäre immer die richtige Reihenfolge der Bytes, auch wenn die Nummer nicht 0xABCDEF00 ist.

Oder, optional, wir können nur Casting verwenden (aber ich denke, das ist hässlich).

+0

alternative Lösung zu verwenden, aber ich denke, es ist ein bisschen zu komplex für diesen kleinen Vergleich. Aber gut zu wissen, dass ich es so machen kann :) – Opa114

+0

* Oder, optional, können wir nur Casting verwenden * Nein, im Allgemeinen können Sie Casting nicht verwenden, da das [strenge Aliasing] verletzt (http://stackoverflow.com)/questions/98650/Was-ist-die-strikte-Aliasing-Regel) und ist daher undefiniertes Verhalten. Es ist auch wahrscheinlich, SIGBUS auf Hardware zu erhöhen, die Ausrichtungsbeschränkungen hat. –

+0

Danke für die Beobachtung, aber ich habe die Gießlösung nicht empfohlen oder ausgearbeitet. Der Code wurde direkt auf den Stack-Overflow geschrieben und funktioniert nicht einmal. Überprüfen Sie eine der Antworten oben für eine Casting-Lösung, bitte, Sie können auch zusammenarbeiten, um sie zu verbessern. – olivecoder

Verwandte Themen