2016-06-14 4 views
3

J'ai un fichier que je veux lire en C++. La première chose que je dois lire et vérifier est le nombre magique du fichier. Dans mon cas, il est le Hex Valeur: 0xABCDEF00C++ lire et comparer le nombre magique à partir du fichier

Je lis et compare le nombre de cette façon:

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; 
} 
} 

Cela fonctionne très bien, mais est-il un moyen de comparer l'ensemble de lecture char [] - Array à la fois? Comme cette façon:

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 ... 
} 

Ce serait bien de savoir s'il y a une telle façon - sinon merci de me TEELING qu'il n'y a pas de telle façon :)

+3

Vous pouvez utiliser memcpy pour copier le contenu du tableau char dans un entier non signé. 'memcpy (& anUnsignedInt, magie, sizeof (unsigned int));' – Christoph

+0

Est-ce que nombre magique dans la gamme de 'long'? Considérons ensuite std :: stol ou familier (stoi pour int, stoll pour long long, ajoutez 'u' avant' i'/'l' /' ll' pour unsigned) ... –

+1

Ne va pas travailler dans un fichier binaire, @LapshinDmitry – user4581301

Répondre

2

bon vieux memcmp pourrait aider. Une fois que vous avez lu le unsigned char magic[4] vous pouvez faire la comparaison aussi simple que:

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

C'est indépendant boutisme.

Si vous savez ce que vous la plate-forme vous donnera le numéro magique et ne se soucient pas de la portabilité sur d'autres plates-formes, vous pouvez traiter directement tout comme uint32_t:

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... 
} 

Ce n'est pas portable sur différentes plates-formes, mais peut être utilisé dans les cas simples ont fait un commentaire dans la police rouge clignotant gras en disant ATTENTION: utilisez uniquement sur grand système endian

+0

Première partie serait la meilleure solution pour moi je pense. Très bien que ce soit endianness indépendant. Mais le 'const char magicref [4] = {0xAB, 0xCD, 0xEF, 0}' shuld être 'const non signé char magicref [4] = {0xAB, 0xCD, 0xEF, 0}'. Sinon je reçois des avertissements du compilateur comme: warning: rétrécissement conversion de '237' de 'int' en 'const char' à l'intérieur – Opa114

+1

Pour être parfait @ Opa114 il devrait plutôt être uint8_t à la place, car ce ne sont pas des caractères sémantiquement. – olivecoder

+0

@olivecoder Merci pour l'indice, j'essaie d'utiliser 'uint8_t' au lieu de' unsigend char' – Opa114

0

Si vous connaissez les ENDIANNESS de votre plate-forme, vous pouvez utiliser une variable uint32_t pour le faire.

Pour un petit système endian, utilisez:

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

Pour un grand système endian, utilisez:

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

Il y a déjà de très bonnes réponses ici! Pour les enregistrements, ici en utilisant une variante equal() de la bibliothèque standard: <algorithm>

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; 

Il est très similaire à la version memcmp() mais il fonctionne avec tout récipient, non seulement les tableaux de CHAR.

Online demo

2

Vous pouvez faire:

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

alors que vous vouliez à l'origine:

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)... 

et vous n'avez pas besoin de se soucier de endianess du tout.

En fonction de l'endianness nombre peut être différent mais cela n'a pas d'importance du tout car ce serait toujours la bonne séquence d'octets même si le nombre n'est pas 0xABCDEF00. Ou, en option, nous pouvons simplement utiliser le casting (mais je pense que c'est moche).

+0

solution alternative, aussi, mais je pense que c'est un peu trop complexe pour cette petite comparaison. Mais bon de savoir que je peux le faire de cette façon :) – Opa114

+0

* Ou, en option, nous pouvons simplement utiliser le casting * Non, en général, vous ne pouvez pas utiliser le casting car cela viole [strict aliasing] (http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) et est donc un comportement indéfini. Il est également susceptible d'augmenter SIGBUS sur le matériel qui a des restrictions d'alignement. –

+0

Merci d'avoir remarqué que, cependant, je n'ai pas recommandé ou élaboré la solution de coulée. Le code a été écrit directement sur le débordement de la pile et ne fonctionne même pas. Cochez l'une des réponses ci-dessus pour une solution de diffusion, vous pouvez également collaborer pour les améliorer. – olivecoder