2012-08-01 131 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声明为size_ttellg()返回-1p的值被设置为4294967295。这意味着seekg()被设置为超出文件末尾。改变p类型std::streamoff并确认调用seekg()成功:

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

,如果确有必要关闭并重新打开同一个文件用于这一目的。

不,这是没有必要,但您需要clear()eof状态从流中。以下是张贴代码的修正版本,一种替代方案:

#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 2012-08-01 11:05:11

+0

我注意到,如果我创建ifstream对象到它的循环中,但是如果我在外部创建它,则不会。是否有必要关闭并重新打开文件以阅读已添加的文件? – Pietro 2012-08-01 11:07:32

+0

@Pietro,你需要在下次读取尝试之前调用'ifs.clear()'来清除'ifstream'的eof状态。我用这种方法来思考'tellg()'和'seekg()'是没有必要的。 – hmjd 2012-08-01 11:14:02

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); 
    } 
} 
相关问题