2012-08-01 16 views
9

私が成長しているファイル(tail -Fが何に似たもの)から読み取るしようとしていますが、私のコードにいくつかの問題がなければならない:C++で成長するテキストファイルを読むには?

string log, logFile("test.log"); 
size_t p = 0; 

while(true) 
{ 
    ifstream ifs(logFile.c_str()); 

    ifs.seekg(p); //*1 

    while(ifs.eof() == false) 
    { 
     getline(ifs, log); 

     cout << log << endl; 

     p = ifs.tellg(); //*2 
    } 

    nanosleep(&pause, NULL); 
} 
// * 1ラインなし

と// * 2の場合、ログファイルは正しく読み込まれますが、新しい行が追加されても何も起こりません。

seekgとtellgを使ってファイルの現在の終了位置を保存しようとしています。再オープンするとそこに行き、追加された内容を読むことができます。

私のコードで何が間違っているのか、この目的のために同じファイルを閉じて再度開く必要があるのか​​どうかを知りたいと思います。

ありがとうございます。

答えて

12

ループがeof()tellg()戻り-1に遭遇したときのように間違っていると、すぐにが必要であるgetline()への呼び出しの後eof()のためのチェックはありません。変更ループ:

while (getline(ifs, log)) 
{ 
    cout << log << endl; 
    p = ifs.tellg(); 
} 

はさらに、pとしてptellg()返り-1値は4294967295に設定されていたときsize_tとして宣言されています。これはseekg()がファイルの最後を超えて設定されていることを意味していました。成功したstd::streamoffpの種類を変更し、seekg()への呼び出しを確認します。

if (ifs.seekg(p)) 
{ 
    while (getline(ifs, log)) 
    { 
     cout << log << endl; 
     p = ifs.tellg(); 
    } 
} 

この目的のために同じファイルを閉じて再度開くことは本当に必要かどうか。

いいえ、それは必要ありませんが、あなたは、ストリームからeof状態をclear()する必要があります。この方法は、私のために忠実に働いている

#include <iostream> 
#include <string> 
#include <fstream> 

int main() 
{ 
    std::ifstream ifs("test.log"); 

    if (ifs.is_open()) 
    { 
     std::string line; 
     while (true) 
     { 
      while (std::getline(ifs, line)) std::cout << line << "\n"; 
      if (!ifs.eof()) break; // Ensure end of read was EOF. 
      ifs.clear(); 

      // You may want a sleep in here to avoid 
      // being a CPU hog. 
     } 
    } 

    return 0; 
} 
+0

適切に動作しています。ありがとうございました。 – Pietro

+0

ループにifstreamオブジェクトを作成すると動作することに気がつきましたが、外部に作成するとそれが動作しません。ファイルを閉じて再オープンする必要がありますか? – Pietro

+0

@Pietroの場合、次の読み込み試行の前に 'ifs.clear()'を呼び出すことによって 'ifstream'のeof状態をクリアする必要があります。このアプローチでは 'tellg()'と 'seekg()'は不要です。 – hmjd

1

::以下は掲載コードの修正版に代わるものです

#include <string> 
#include <chrono> 
#include <thread> 
#include <fstream> 
#include <iostream> 

int main(int, char* argv[]) 
{ 
    // open file passed in on command line (at end of file) 
    std::ifstream ifs(argv[1], std::ios::ate); 

    if(!ifs.is_open()) 
    { 
     std::cerr << "ERROR: opening log file: " << argv[1] << '\n'; 
     return 1; 
    } 

    // remember file position 
    std::ios::streampos gpos = ifs.tellg(); 

    std::string line; 
    bool done = false; 

    while(!done) 
    { 
     // try to read line 
     if(!std::getline(ifs, line) || ifs.eof()) 
     { 
      // if we fail, clear stream, return to beginning of line 
      ifs.clear(); 
      ifs.seekg(gpos); 

      // and wait to try again 
      std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
      continue; 
     } 

     // remember the position of the next line in case 
     // the next read fails 
     gpos = ifs.tellg(); 

     // process line here 
     std::cout << "line: " << line << std::endl; 
    } 
} 
0

このコードは、私の作品:今それを

struct timespec pause; 
pause.tv_sec = 1; 
pause.tv_nsec = 0; 

std::ifstream ifs("test.log"); 
std::streamoff p; 

if(ifs.is_open()) 
{ 
    std::string line; 

    while(true) 
    { 
     if(ifs.seekg(p)) 
     { 
      while(std::getline(ifs, line)) 
      { 
       std::cout << line << std::endl; 
       p = ifs.tellg(); 
      } 
     } 

     ifs.clear(); 

     nanosleep(&pause, NULL); 
    } 
} 
関連する問題