从持续更新的文件中读取 [英] Read from a file that is continuously being updated

查看:209
本文介绍了从持续更新的文件中读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一些C代码来处理文件中的一些数据,但是我刚刚知道文件将不断添加到(大约1次/秒,也许更快)。所以我想知道如何继续阅读文件,因为它被添加到。然后,当我到最后,等到下一行被添加,然后处理它。然后再等待,然后处理,依此类推。 (1){
fgets(line,sizeof(line),file);

  while 
while(line == NULL){
// wait?然后尝试再读一遍?

//标记行并在这里做我的东西

code $


<我想我可以用inotify,但是我没有办法。有没有人有任何建议?

解决方案

最有效的方法是使用inotify,直接的方法是使用直接读取()系统调用。
$ b

使用 inotify



下面的代码可能会给你一些帮助,它在Debian 7.0,GCC 4.7上运行良好:

  / *这是通知我们创建文件的示例程序,文件删除发生在/ tmp / test_inotify文件中* / 
//修改自:http://www.thegeekstuff。 inotify -c-program-example /
#include
#include< stdlib.h>
#include< errno.h>
#include< unistd.h>
#include< sys / types.h>
#include< sys / inotify.h>
$ b $ #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];
$ b $ / *创建INOTIFY实例* /
fd = inotify_init();
/ *检查错误* /
if(fd <0){
perror(inotify_init error);
}

/ *将/ tmp / test_inotify测试添加到监视列表中。在这里,
*建议是在添加到监控列表之前验证
*目录的存在。
* /
wd = inotify_add_watch(fd,/ tmp / test_inotify,IN_CREATE | IN_DELETE | IN_ACCESS | IN_MODIFY | IN_OPEN);

/ *读取以确定事件发生在/ tmp / test_inotify文件中。
*实际上这个读取块直到发生变化事件
* /
length = read(fd,buffer,EVENT_BUF_LEN);
/ *检查错误* /
if(length <0){
perror(read);
}

/ *实际读取返回发生变化事件的列表。
*在这里,逐个阅读更改事件并相应地进行处理。
* /
while(i< length){
struct inotify_event * event =(struct inotify_event *)& buffer [i];
if(event-> len == 0){
//对于单个文件观看,event->名称是空的,而event-> len = 0
printf (单个文件观看事件发生了......);
} else if(event-> len){
if(event-> mask& IN_CREATE){
if(event-> mask& IN_ISDIR){
printf(新建目录%s created.\\\
,event->名称);
} else {
printf(New file%s created.\\\
,event-> name);
} else if(event-> mask& IN_DELETE){
if(event-> mask& IN_ISDIR){
printf(Directory%s deleted 。\\\
,event-> name);
} else {
printf(File%s deleted.\\\
,event-> name);
} else if(event-> mask& IN_ACCESS){
if(event-> mask& IN_ISDIR){
printf(Directory%s accessible 。\\\
,event-> name);
} else {
printf(File%s accessible。\\\
,event-> name);
printf(Directory%s modified)
}
} else if(event-> mask& IN_MODIFY){
if(event-> mask& IN_ISDIR) 。\\\
,event-> name);
} else {
printf(File%s modified。\\\
,event-> name);
printf(Directory%s open)
}
else else(event-> mask& IN_OPEN){
if(event-> mask& IN_ISDIR) 。\\\
,event-> name);
} else {
printf(File%s opened。\\\
,event-> name);

} else {
printf(目录或文件被其他模式访问);
}
}
i + = EVENT_SIZE + event-> len;
}

/ *从监视列表中移除/ tmp / test_inotify目录。 * /
inotify_rm_watch(fd,wd);

/ *关闭INOTIFY实例* /
close(fd);

}

运行上述程序时。您可以通过创建一个名为 / tmp / test_inotify 的文件或者directoy来测试它。



可以找到详细的解释此处



使用读取系统调用



如果一个文件已经打开,并且已经读取到当前的结尾文件大小。 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 \\\
);
exit(-1);
}

int nbytes;
while(1){
nbytes = read(filed,buf,16);
printf(从文件读取%d个字节,nbytes);
if(nbytes> 0){
split_buffer_by_newline(buf); //用新行分割缓冲区
}
sleep(1);
}
return 0;

$ / code $ / pre
$ b $ h1

$
  • 感谢Jonathan Leffler的评论

  • http://www.thegeekstuff.com/2010/04/inotify-c-program-example/


  • I am writing some C code to process some data in a file, but I just learned that the file is going to be constantly added to (about 1 time/second, maybe faster). So I'm wondering how do I keep reading from the file as its being added to. Then when I get to the end, wait until the next line is added and then process it. Then wait again and then process, and so on and so on. I have something like:

    while(1){
        fgets(line, sizeof(line), file);
        while(line == NULL){
           //wait ?  then try to read again?
        }
        //tokenize line and do my stuff here
    }
    

    I thought I could maybe use inotify, but I am getting nowhere with that. Does anyone have any advice?

    解决方案

    The most efficient way is using inotify, and the direct way is using the read() system call directly.

    using inotify

    The following code may give you some help, It works well on 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 );
    
    }
    

    When runing the above program. You could test it by create a file or directoy named /tmp/test_inotify.

    A detailed explanation could be found here

    Use read system call

    If a file is open, and have read to the end of current file size. the read() system call will return 0. And if some writer wrote N bytes to this file later, and then the read() will just return min(N, buffersize).

    So it works correctly for your circumstance. Following is an examples of the code.

    #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;
    }
    

    Reference

    这篇关于从持续更新的文件中读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆