2010-04-23 252 views
14

我想用C++创建一个与“tail -f”相同功能的小代码:观察文本文件中的新行并在标准输出中显示它们。在C++中实现“tail -f”

的想法是有一个监视文件

有一个简单的办法做到这一点不开,每次关闭文件的主题?

+0

你可能也很难在纯C做这++ 。你将不得不使用一些平台特定的API。 (对于初学者,我不认为你可以用C++非独占地打开一个文件。) – sbi 2010-04-23 07:51:49

+1

@sbi我不认为C++标准对排他性有什么要说的。 – 2010-04-23 07:54:08

+1

有没有理由不能使用tail -f? – 2010-04-23 08:03:00

回答

11

只要继续阅读文件。如果读取失败,则不执行任何操作。没有必要反复打开和关闭它。但是,如果您的操作系统提供这些功能,您将发现使用特定于操作系统的功能来监视文件效率更高。

+2

+1:尝试阅读到目前为止的文件末尾(对于合理长度的文件),每秒一次在实践中很便宜。你只是阅读,直到你完成,然后睡一秒,然后再次尝试阅读。 (如果你在Windows上,注意用正确的共享标志打开,这样你就不会锁定其他的作者,这可能意味着使用本地IO调用,而不是C++标准的调用...) – 2010-04-23 08:23:34

11

查看Linux上的inotify或Mac OS上的kqueue。

Inotify是Linux内核子系统,允许您订阅文件上的事件,并在文件发生偶发事件时向您的应用程序报告。

+0

Windows有一个等价的API用于在文件更改时发送通知。 – 2010-04-23 17:49:54

1

我在one of Perl manuals中读到这个,但它很容易翻译成标准C,而标准C又可以翻译成istream s。

seek FILEHANDLE,POSITION,WHENCE 
     Sets FILEHANDLE's position, just like the "fseek" call of 
     "stdio". 
     <...> 
     A WHENCE of 1 ("SEEK_CUR") is useful for not moving the file 
     position: 

      seek(TEST,0,1); 

     This is also useful for applications emulating "tail -f". Once 
     you hit EOF on your read, and then sleep for a while, you might 
     have to stick in a seek() to reset things. The "seek" doesn't 
     change the current position, but it does clear the end-of-file 
     condition on the handle, so that the next "<FILE>" makes Perl 
     try again to read something. We hope. 

至于我记得,fseek被称为iostream::seekg。所以你应该基本上做同样的事情:寻找文件的结尾,然后睡觉并用ios_base::cur标志再次寻找以更新文件结束并读取更多数据。

代替sleep ING,你可以(在从一个模拟的文件读取,实际上是块)正是使用的inotify,如the other answer建议,睡觉,直到该文件被更新/关闭。但这是Linux特有的,并不是标准的C++。

+0

热爱“我们希望”关门。“这很奇怪,但它很好,因为它很奇怪”以及很多其他自我炫耀的实现,它们都是perl的典型代表... – 2010-04-23 09:17:37

+0

@Stefano - 嗯,这里很好,因为它涉及到Perl的linewise实现文件阅读(''),而不是关于'fseek'如何工作。我希望。 – 2010-04-23 09:20:06

1

我也需要实现这一点,我只是写了一个标准C++的快速入门。黑客在文件中搜索最后一个0x0A(换行字符),并在最后一个换行值变为较大值时输出该换行之后的所有数据。该代码是在这里:

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

using namespace std; 


int find_last_linefeed(ifstream &infile) { 

    infile.seekg(0,ios::end); 
    int filesize = infile.tellg(); 

    for(int n=1;n<filesize;n++) { 
    infile.seekg(filesize-n-1,ios::beg); 

    char c; 
    infile.get(c); 

    if(c == 0x0A) return infile.tellg(); 
    } 
} 


int main() { 


    int last_position=-1; 
    for(;;) { 

    ifstream infile("testfile"); 
    int position = find_last_linefeed(infile); 

    if(position > last_position) { 
     infile.seekg(position,ios::beg); 
     string in; 
     infile >> in; 
     cout << in << endl; 
    } 
    last_position=position; 

    sleep(1); 
    } 

} 
2

相同https://stackoverflow.com/a/7514051/44729除了下面的代码使用,而不是GETC函数getline,而不是跳过新线

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

using namespace std; 

static int last_position=0; 
// read file untill new line 
// save position 

int find_new_text(ifstream &infile) { 

    infile.seekg(0,ios::end); 
    int filesize = infile.tellg(); 

    // check if the new file started 
    if(filesize < last_position){ 
     last_position=0; 
    } 
    // read file from last position untill new line is found 

    for(int n=last_position;n<filesize;n++) { 

     infile.seekg(last_position,ios::beg); 
     char test[256]; 
     infile.getline(test, 256); 
     last_position = infile.tellg(); 
     cout << "Char: " << test <<"Last position " << last_position<< endl; 
     // end of file 
     if(filesize == last_position){ 
     return filesize; 
     } 

    } 

    return 0; 
} 


int main() { 

    for(;;) { 
    std::ifstream infile("filename"); 
    int current_position = find_new_text(infile); 
    sleep(1); 
    } 

} 
+0

文件大小 Angela 2014-11-06 01:01:55