我正在编写一些C代码来处理文件中的一些数据,但我刚刚知道文件将不断添加到(大约1次/秒,也许更快)。 所以我想知道如何继续阅读文件,因为它被添加到。 然后,当我到最后,等到下一行被添加,然后处理它。 然后再等待,然后处理,依此类推。 我有这样的东西:
while(1){ fgets(line, sizeof(line), file); while(line == NULL){ //wait ? then try to read again? } //tokenize line and do my stuff here }
我以为我可以用inotify,但是我没有办法。 有人有build议吗?
最有效的方法是使用inotify,直接的方法是直接使用read()
系统调用。
inotify
下面的代码可能会给你一些帮助,在Debian 7.0,GCC 4.7上效果很好:
/*This is the sample program to notify us for the file creation and file deletion takes place in “/tmp/test_inotify” file*/ // Modified from: http://www.thegeekstuff.com/2010/04/inotify-c-program-example/ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/inotify.h> #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) int main( ) { int length, i = 0; int fd; int wd; char buffer[EVENT_BUF_LEN]; /*creating the INOTIFY instance*/ fd = inotify_init(); /*checking for error*/ if ( fd < 0 ) { perror( "inotify_init error" ); } /* adding the “/tmp/test_inotify” test into watch list. Here, * the suggestion is to validate the existence of the * directory before adding into monitoring list. */ wd = inotify_add_watch( fd, "/tmp/test_inotify", IN_CREATE | IN_DELETE | IN_ACCESS | IN_MODIFY | IN_OPEN ); /* read to determine the event change happens on “/tmp/test_inotify” file. * Actually this read blocks until the change event occurs */ length = read( fd, buffer, EVENT_BUF_LEN ); /* checking for error */ if ( length < 0 ) { perror( "read" ); } /* actually read return the list of change events happens. * Here, read the change event one by one and process it accordingly. */ while ( i < length ) { struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ]; if( event->len == 0) { // For a single file watching, the event->name is empty, and event->len = 0 printf(" Single file watching event happened\n"); } else if ( event->len ) { if ( event->mask & IN_CREATE ) { if ( event->mask & IN_ISDIR ) { printf( "New directory %s created.\n", event->name ); } else { printf( "New file %s created.\n", event->name ); } } else if ( event->mask & IN_DELETE ) { if ( event->mask & IN_ISDIR ) { printf( "Directory %s deleted.\n", event->name ); } else { printf( "File %s deleted.\n", event->name ); } } else if( event->mask & IN_ACCESS ) { if ( event->mask & IN_ISDIR ) { printf( "Directory %s accessed.\n", event->name ); } else { printf(" File %s accessed. \n", event->name ); } } else if( event->mask & IN_MODIFY ) { if ( event->mask & IN_ISDIR ) { printf( "Directory %s modified.\n", event->name ); } else { printf(" File %s modified. \n", event->name ); } } else if( event->mask & IN_OPEN ) { if ( event->mask & IN_ISDIR ) { printf( "Directory %s opened.\n", event->name ); } else { printf(" File %s opened. \n", event->name ); } } else { printf( "Directory or File is accessed by other mode\n"); } } i += EVENT_SIZE + event->len; } /* removing the “/tmp/test_inotify” directory from the watch list. */ inotify_rm_watch( fd, wd ); /* closing the INOTIFY instance */ close( fd ); }
运行上述程序时。 您可以通过创建名为/tmp/test_inotify
的文件或/tmp/test_inotify
来测试它。
详细的解释可以在这里找到
read
系统调用 如果文件已打开,并且已经读到当前文件大小的末尾。 read()
系统调用将返回0
。 如果稍后某个作者写了N
个字节到这个文件,然后read()
将返回min(N, buffersize)
。
所以它适用于你的情况。 以下是代码示例。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> typedef int FD ; int main() { FD filed = open("/tmp/test_inotify", O_RDWR ); char buf[128]; if( !filed ) { printf("Openfile error\n"); exit(-1); } int nbytes; while(1) { nbytes = read(filed, buf, 16); printf("read %d bytes from file.\n", nbytes); if(nbytes > 0) { split_buffer_by_newline(buf); // split buffer by new line. } sleep(1); } return 0; }
您可以使用select()
和fileno(file)
作为文件描述符。 select
将返回一个超时(如果你设置一个超时),或者当你可以从文件读取。
使用select
可以是一个不错的选择,但是如果你不想使用它,你可以在读取值之前添加一个小的毫秒睡眠时间。