2017-05-31 155 views
1

我在玩ifstream來熟悉它。我正在嘗試使用seekg來告訴文件的位置,但它給了我錯誤的結果。ifstream :: seekg給出了錯誤的結果

的想法是:

  1. 打開的文件的文件
  2. 打印位置
  3. 從文件中讀取一個字符
  4. 文件
  5. 打印位置讀取一個字符從文件
  6. 文件的打印位置
  7. 關閉文件。

原始文件看起來像這樣(Windows格式):

file.txt的

aA 
bB 
cC 
dD 
eE 
fF 

運行我的代碼,我得到的結果:

position: 0 
got: a 
position: 6 
got: A 
position: 7 

然而,對於此文件:

file.txt的

aAbBcCdDeEfF 

我得到這些結果

​​

這裏是我使用的代碼:

TEST.CPP(MinGW的/ gcc5.3)

#include <fstream> 
#include <iostream> 

using namespace std; 

static char s[10]; 

int main(int argc, char **argv) 
{ 
    ifstream f("file.txt");  
    cout << "position: " << f.tellg() << "\n"; 
    f.read(s, 1); 
    cout << "got: " << s << "\n"; 
    cout << "position: " << f.tellg() << "\n"; 
    f.read(s, 1); 
    cout << "got: " << s << "\n"; 
    cout << "position: " << f.tellg() << "\n";  
    f.close(); 

    return 0; 
} 

這裏是th兩個文本文件分別Ë兩個十六進制編輯觀點:

enter image description here 修改enter image description here

我希望既能產生結果。0,1,2分別,然而這不是原始實驗的情況。

有人可以解釋這裏發生了什麼嗎?

問題

  1. 我應該怎麼做才能得到正確的文件中的位置?

答:使用ifstream("file.txt", ios_base::in | ios_base::binary)構造了ifstream("file.txt")構造。

  1. 是什麼導致f.tellg默認給出這些奇怪的值0,6,7而不是預期的1,2,3?

可能的解釋(測試由以下霍爾特答案)在此代碼度假村

f.tellg到f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in)其是負責產生值0,6,7(但只有當ios_base::binary是不在施工/開放時指定)。

#include <fstream> 
#include <iostream> 

using namespace std; 

static char s[10]; 

int main(int argc, char **argv) 
{ 
    ifstream f("file.txt");  
    cout << "position: " << f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in) << "\n"; 
    f.read(s, 1); 
    cout << "got: " << s << "\n"; 
    cout << "position: " << f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in) << "\n"; 
    f.read(s, 1); 
    cout << "got: " << s << "\n"; 
    cout << "position: " << f.rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in) << "\n"; 
    f.close(); 

    return 0; 
} 

注意傳遞ios::in | ios::binary作爲第二個參數的構造函數ifstream的使這兩個文件像預期的那樣,但我想也知道是什麼引起的默認行爲給這些奇怪所以tellg值。

備註區別於tellg() function give wrong size of file?。這個問題有默認的ios :: binary設置,並使用seek;這裏的這個問題既有ios :: binary也沒有,並且不使用seek。總的來說,這兩個問題有不同的背景,並且知道這個問題的答案不能回答這個問題。

+0

比較十六進制編輯器中的文件。也許在文件開始時有一個BOM或一些奇怪的看不見的廢話,OS會爲你讀取和跳過(除非你以二進制模式打開文件)。 – tambre

+0

在底部添加了十六進制視圖。前兩個字符是相同的,所以我不知道它會如何影響seekg。 – Dmitry

+0

你在使用什麼操作系統和編譯器?請包括確切的版本。 – tambre

回答

5

沒有什麼作爲由tellg()返回的值是「錯誤」的結果是:如果在文件中文本模式被打開,返回值是不確定(即它有不同之處在於它可以用於任何意義作爲seekg()的輸入)。

基本上,在basic_fstreamtellg()呼叫回落到std::ftell 功能,它說(C標準,§ 7.21.9.4 [文件定位功能],強調的是礦):

long int ftell(FILE *stream);

ftell函數獲取stream指向的流的文件位置指示符的當前值。 [...]對於文本流,其文件位置指示器包含未指定的信息fseek函數可用於將 流的文件位置指示符返回到其在調用ftell時的位置;兩個這樣的返回值之間的差異是不一定是寫或讀的字符數量的有意義的度量。

tellg()回落到rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in),其回退到basic_filebuf::seekoff(0, std::ios_base::cur, std::ios_base::in)然後回落到std::ftell()

+0

我通過直接去pubseekoff來測試你的答案,它確實給出了相同的錯誤值,但只有ifstream的構造函數沒有被賦予'ios_base :: in |的ios_base :: binary'。仍然好奇背後幕後發生這些1,6,7結果而不是0,1,2。 – Dmitry

+0

@Dmitry這是高度依賴操作系統(和編譯器) - 特別是在Windows上,你有一些在文本模式下的翻譯,例如爲''\ n''。我用你的文本文件嘗試了你的代碼,我甚至沒有得到和你一樣的結果(我得到了7 8和2 3)。這可能是因爲我在每個文件的末尾添加了一個額外的'\ n',這將確認在Windows上轉換'\ n''的影響。 – Holt