2009-08-05 150 views
0

我有一個程序正在拖曳一個正在增長的文件。std :: getline和eol vs eof

我試圖避免從文件中抓取部分行(例如,在該行完全由其他進程寫入之前讀取)。我知道這是發生在我的代碼中,所以我試圖特別抓住它。

有沒有一種理智的方式來做到這一點?

這裏就是我想:

if (getline (stream, logbuffer)) 
{ 
    if (stream.eof()) 
    { 
     cout << "Partial line found!" << endl; 
     return false; 
    } 
    return true; 
} 
return false; 

但是,我不能輕易地重現該問題,所以我不知道我在這個代碼檢測它。 std :: getline剝離換行符,所以我無法檢查緩衝區中是否存在換行符。我的日誌消息(上面)從不絆倒。

是否有其他一些方法來檢查我想要檢測的內容?有沒有辦法知道我讀的最後一行是否沒有找到EOL字符而擊中EOF?

謝謝。

+1

爲什麼不修改其他進程只刷新其輸出緩衝區到新行上的文件? – 2009-08-05 20:23:22

+0

我沒有擁有其他進程,也沒有任何對其行爲的控制權。整合的樂趣。 – Joe 2009-08-05 20:26:00

+0

確實。向其他部門投訴? – 2009-08-05 20:26:59

回答

3

這不會是真的:

if (getline (stream, logbuffer)) 
{ 
    if (stream.eof()) 
    { 
     /// will never get here 

如果getline()工作,流不能在一個EOF狀態。 eof()和相關的狀態測試只適用於上一次讀取操作的結果,如getline() - 它們不能預測下一次讀取的結果。

據我所知,沒有辦法做你想做的事。但是,如果其他進程一次寫入一行,那麼您說您遇到的問題應該非常少見(根據我的經驗不存在),這在某種程度上取決於您正在使用的操作系統。我懷疑問題在別處,可能在你的代碼中。拖尾文件是一件非常常見的事情,而且通常不需要使用特殊代碼來執行該操作。

但是,你應該找到你需要閱讀的部分線路,基本算法如下:

forever do 
    wait for file change 
    read all possible input using read or readsome (not getline) 
    chop input into lines and possible partial line 
    process as required 
end 
+1

不正確。如果文件中的最後一行不以換行符結束,則getline將成功(failbit未設置),但流仍會進入EOF狀態(因爲getline嘗試讀取更多字符)。即使設置了eofbit,getline也會返回所有讀取到的最後一行logbuffer中的內容。 – Tronic 2010-01-09 15:00:09

0

即使其他程序沒有寫完的文件,這也正是該文件中行結束,所以除了等待查看其他程序是否寫入新內容之外,沒有辦法分辨其差異。

編輯:如果您只是想知道該行是否以換行符結束,您可以編寫自己的getline函數,直到它遇到新行但不刪除它。

+0

我猜想我想辨別的是最後一行是否以換行符結束。 – Joe 2009-08-05 20:17:49

0

我得把問題與你在這裏做一個發言:

但是,我不能輕易地重現該問題,所以我不知道我在這個代碼檢測它。

從你所說的話看來,如果是你說的話,複製你的問題會非常容易。您可以在一些文本編輯器中輕鬆創建文本文件 - 只需確保最後一個文件在EOF中結束,而不是進入新行。然後將該程序指向該文件並查看結果。

+0

嗯。好點子。 – Joe 2009-08-05 20:15:21

+0

這確實不能重現問題。它再現了OP對它的解釋,這可能是錯誤的。 – 2009-08-05 20:22:41

1

istream對象如std::cin有一個get function,當它到達換行而不從流中提取時停止讀取。那麼你可以用peek()get()來查看它是否確實是換行符。問題在於,您必須知道來自其他應用程序的最大行數。示例(未經測試)的代碼如下:

char buf[81]; // assumes an 80-char line length + null char 
memset(buf, 0, 81); 

if (cin.get(buf, 81)) 
{ 
    if (cin.peek() == EOF) // You ran out of data before hitting end of line 
    { 
     cout << "Partial line found!\n"; 
    } 
} 
+0

我的評論相當晚,但我相信這是正確的答案。使用'std :: istream :: peek()'來檢查'EOF'會讓你知道是否返回了'std :: getline()',因爲它找到了換行符或者因爲它到達了文件的末尾。我剛剛在[我的最新博客文章](https://v1ntage.io/2018/01/10/episode-007-handling-eof-with-stdgetline/)中討論了這個問題。 – v1bri 2018-01-11 04:13:36