2016-06-14 35 views
3

我有i文件我想用C++讀取。首先我必須閱讀並檢查文件的幻數。在我的情況下,它是十六進制值:0xABCDEF00C++從文件中讀取和比較幻數

我閱讀和比較的數字是這樣的:

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

這工作得很好,但有沒有辦法比較全讀的char [] - 陣列一次?像這樣:

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

會很高興地知道,如果有這樣一種方式 - 如果不是感謝teeling我,有沒有這樣的方式:)

+3

您可以使用memcpy將char數組的內容複製到unsigned int中。 'memcpy(&anUnsignedInt,magic,sizeof(unsigned int));' – Christoph

+0

是'long'範圍內的神奇數字嗎?然後考慮'std :: stol'或熟悉的('stoi'代表'int','stoll'代表'long long',在'i' /'l' /'ll'之前加'u'代表unsigned)... –

+1

不會在二進制文件中工作,@LapshinDmitry – user4581301

回答

2

好老memcmp可以幫助這裏。一旦您已經閱讀unsigned char magic[4]你可以做的比較簡單,如:

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

這是字節順序無關。

如果你知道你的平臺將會給你一個神奇的數字,不關心其他平臺的可移植性,可以直接處理一切爲uint32_t

​​3210

這不是在不同的平臺之間移植,但可以在簡單的情況下使用,提供了一個粗體紅色閃爍字體的評論說請注意:只能用於大端系統

+0

第一部分對我來說是最好的解決方案。非常好,它是endianness獨立的。但'const char magicref [4] = {0xAB,0xCD,0xEF,0}'是'const unsigned char magicref [4] = {0xAB,0xCD,0xEF,0}'。如果沒有,我會得到如下的編譯器警告:warning:將'237'從'int'縮小到'const char'在 – Opa114

+1

之內要完美@ Opa114它實際上應該是uint8_t,因爲它們不是語義上的字符。 – olivecoder

+0

@olivecoder謝謝你的提示,我嘗試使用'uint8_t'而不是'unsigend char' – Opa114

0

如果你知道你的平臺的字節序,你可以使用一個uint32_t變量來做到這一點。

對於小端系統,請使用:

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

對於大端系統,使用:

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

這裏已經有很好的答案!對於記錄,在這裏使用標準<algorithm>equal()變體:

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; 

這是非常相似的memcmp()版本,但它與任何容器,不僅字符數組工作。

Online demo

2

你可以這樣做:

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

那麼,你本來想:

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

,你不需要關心字節序的。

取決於字節序的數量可以是不同的,但根本不重要,因爲即使數字不是0xABCDEF00,它也總是正確的字節序列。

或者,我們可以選擇鑄造(但我認爲這很醜)。

+0

替代解決方案,但是我認爲對於那種小小的比較它有點複雜。但很好的知道,我可以這樣做:) – Opa114

+0

*或者,可選地,我們可以只使用鑄造*不,一般來說,你不能使用鑄造違反[嚴格別名](http://stackoverflow.com/questions/98650/what-is-strict-aliasing-rule),因此是未定義的行爲。它也可能在具有對齊限制的硬件上引發SIGBUS。 –

+0

感謝您觀察,但我沒有推薦或詳細說明鑄造解決方案。代碼直接寫入堆棧溢出,甚至沒有工作。請檢查上述答案中的一個,以獲得鑄造解決方案,還可以協作改進它們。 – olivecoder