2017-04-04 48 views
1

我有一個std::fstream,我使用std :: fstream :: tellg()不正確地輸出文件遊標指針?

std::fstream myFile { "C:/path/to/file.txt" }; 

當我想讀的第一個字節進口的,我用

char c; 
cout << myFile.tellg() << endl; // Correctly outputs 0 (begining of file) 
myFile.read(&c, 1); 
cout << myFile.tellg() << endl; // Should output 1, but it outputs 
           // FFFFFFFFFFFFFFFA 
myFile.read(&c, 1); 
cout << myFile.tellg() << endl; // Should output 2, but it outputs 
           // FFFFFFFFFFFFFFFB 

這裏發生了什麼?

我試圖把

midi_file.seekg(0, ios_base::beg); 

midi_file.seekg(0, myFile.beg); 

但光標移動到FFFFFFFFFFFFFFFA每當我試圖讀取一個字節。

編輯:

我不知道這是否有事情做,但我做了一個字節序的測試,這些都是結果:

bool endianness = *reinterpret_cast<short*>("10") & 1; // Outputs 1 

編輯2:

該文件已損壞,因爲輸出與其他文件不同,但爲什麼?

這裏是從文件中的字節數據,從HXD取,這是一個.midi文件:

4D 54 68 64 00 00 00 06 00 01 00 03 00 04 4D 54 
72 6B 00 00 00 A1 00 C0 69 00 90 3C 5A 01 41 5A 
01 45 5A 01 48 5A 01 49 5A 01 48 5A 01 45 5A 01 
41 5A 01 3C 5A 01 37 5A 01 33 5A 01 30 5A 01 30 
5A 01 30 5A 01 33 5A 01 37 5A 01 3C 5A 01 41 5A 
01 45 5A 01 48 5A 01 49 5A 01 48 5A 01 45 5A 01 
41 5A 01 3C 5A 01 37 5A 01 33 5A 01 30 5A 01 30 
5A 01 30 5A 01 33 5A 01 37 5A 01 3C 5A 01 41 5A 
01 45 5A 01 48 5A 01 49 5A 01 48 5A 01 45 5A 01 
41 5A 01 3C 5A 01 37 5A 01 33 5A 01 30 5A 01 30 
5A 01 30 5A 01 33 5A 01 37 5A 01 3C 5A 01 41 5A 
01 45 00 00 FF 2F 00 4D 54 72 6B 00 00 00 41 00 
C1 72 05 91 3C 5A 00 40 5A 00 43 5A 00 48 5A 0A 
35 5A 00 41 5A 00 44 5A 00 49 5A 0A 37 5A 00 40 
5A 00 43 5A 00 48 5A 0A 41 5A 00 47 5A 0A 30 5A 
00 40 5A 00 43 5A 00 48 5A 05 32 00 00 FF 2F 00 
4D 54 72 6B 00 00 00 26 00 C2 47 0A 92 50 64 01 
52 64 09 50 78 00 52 78 0A 50 00 01 52 00 09 50 
78 01 50 00 0A 52 00 00 50 00 00 FF 2F 00 

EDIT 3:

下面是該測試的全碼:

#include <fstream> 
#include <iostream> 

int main() { 
    cout << std::hex << std::setfill('0') << std::uppercase; 

    fstream midi_file{ "D:/Descargas/OutFile.midi" }; 

    cout << midi_file.good() << endl; // Outputs 1 

    char c; 
    cout << midi_file.tellg() << endl; // Correctly outputs 0 (begining of file) 
    midi_file.read(&c, 1); 
    cout << midi_file.tellg() << endl; // Erroneously outputs FFFFFFFFFFFFFFFA 
    midi_file.read(&c, 1); 
    cout << midi_file.tellg() << endl; // Erroneously outputs FFFFFFFFFFFFFFFB 

    // Endianness test: 
    cout << (*reinterpret_cast<short*>("10") & 1) << endl; // Outputs 1 

    return 0; 
} 
+0

'myFile'在讀取之前和之後都處於良好狀態? – Angew

+0

@Angew Hmm,'myFile.badbit'返回'4','myFile.failbit'返回'2'。但是'myFile.bad()'和'myFile.fail()'返回'0'。 – Garmekain

+0

我認爲當構造'std :: fstream'時,花括號'{}'是一個錯字?應該是'()'。它甚至用'{}'編譯? – freakish

回答

0

文件打開方式必須是ios::binary模式沒有趕上特殊字符。

1

返回值爲tellg的是不是的一個數字。這是一個pos_type,它有一些規則需要遵循,但在印刷不是其中之一時可以理解。請參閱http://en.cppreference.com/w/cpp/io/fpos

它的主要目的是允許查找操作返回到保存的位置。

此外,你的「排序測試」是非常非常混亂。將字符串重新解釋爲簡短字符? C不會那樣工作。 也許如果你曾經使用"\x01\x00"

+0

這是一個字符串,它只是一個'const char *',並且由於char字符串長度爲2個字節,所以它可以完美地轉換爲2個字節的變量,在本例中爲'short'。我知道''0'是十進制的'48',所以'&1'部分告訴我們這個字符的數字是否是奇數。 「0」不是「1」,所以如果「0」是MSB,則「(0x100 * 48 + 49)&1」將返回true,但如果「1」是MSB,那麼'(0x100 * 49 + 48)&1'將返回false。 – Garmekain

+0

@Garmekain:如果你喜歡這樣做,我猜。但它讓你看起來像是一個懵懂無知的人,他很幸運。 –

+1

@Garmekain「它可以完美鑄造」不,它不能。它甚至不應該編譯,因爲你不能用'reinterpret_cast'拋棄'const',並且當你的編譯器給你一些鬆弛並且允許它編譯時,它可以在運行時由於錯誤對齊而崩潰,或者編譯器可以扔掉你的整個程序,因爲它展示UB並用NOP替換它。 –