2014-03-06 21 views
0

嘿大家這可能會變成一個簡單的愚蠢的問題,但一直讓我頭痛一陣子。我正在讀取來自命名二進制標記文件的數據,並且該代碼正在工作,除非我嘗試讀取big-endian數字。該得到的整數代碼如下所示:從文件讀取二進制給出負數

long NBTTypes::getInteger(istream &in, int num_bytes, bool isBigEndian) 
{ 
    long result = 0; 
    char buff[8]; 

    //get bytes 
    readData(in, buff, num_bytes, isBigEndian); 

    //convert to integer 
    cout <<"Converting bytes to integer..." << endl; 
    result = buff[0]; 
    cout <<"Result starts at " << result << endl; 
    for(int i = 1; i < num_bytes; ++i) 
    { 
     result = (result << 8) | buff[i]; 
     cout <<"Result is now " << result << endl; 
    } 
    cout <<"Done." << endl; 

    return result; 
} 

而且READDATA功能:

void NBTTypes::readData(istream &in, char *buffer, unsigned long num_bytes, bool BE) 
{ 
    char hold; 

    //get data 
    in.read(buffer, num_bytes); 

    if(BE) 
    { 
     //convert to little-endian 
     cout <<"Converting to a little-endian number..." << endl; 
     for(unsigned long i = 0; i < num_bytes/2; ++i) 
     { 
      hold = buffer[i]; 
      buffer[i] = buffer[num_bytes - i - 1]; 
      buffer[num_bytes - i - 1] = hold; 
     } 
     cout <<"Done." << endl; 
    } 
} 

此代碼,最初的工作(給正確的正值),但現在不管是什麼原因,我得到的值無論是過度還是下降。我錯過了什麼?

+0

號碼是多少你期待?有可能這個數字太大而不能代表那麼久?嘗試使用無符號長整型。 – TripShock

+0

向我們展示'readData'的輸入和輸出示例,包括'isBigEndian'的設置。 –

+0

感謝您的意見。我期望的數字是128,但是我得到了-128。二進制輸入是一個大端短(128)。返回的字節表明我應該得到正確答案 –

回答

1

您的字節順序交換很好,但是從字節序列構建整數不是。

首先,你得到的字節順序是錯的:你讀入的第一個字節變成最重要的字節,而它應該是相反的。

然後,當OR從陣列中的字符-ing分詞,要知道,除非你掩蓋他們出去,他們都提升到一個int,其中,已簽署char,設置了很多附加位。

最後,當longnum_bytes寬時,需要sign-extend這個位。

此代碼:

union { 
    long s;   // Signed result 
    unsigned long u; // Use unsigned for safe bit-shifting 
} result; 

int i = num_bytes-1; 
if (buff[i] & 0x80) 
    result.s = -1; // sign-extend 
else 
    result.s = 0; 
for (; i >= 0; --i) 
    result.u = (result.u << 8) | (0xff & buff[i]); 
return result.s; 
+0

我很欣賞這個答案。我從來沒有想過簽署延期或掩蓋!我現在離我的Minecraft編程更近了一步:) –