读取不断更新的文件,并等待将新数据写入C中的文件

时间:2017-12-27 05:32:41

标签: c file-handling

我有一个日志文件,我想在C中编写一个程序来读取该日志文件,并在达到EOF时等待新数据。 我不想在我的代码中使用tail -f。 我尝试了以下代码,但它无法正常工作:

#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>

#define PATH "/home/sanket/demo.txt"

int main(void)
{
        FILE * fp;
    int fd;
    char * line = NULL;
    size_t len = 0;
    ssize_t read1;
    int notify_fd;
    int wd,length ,i=0;
    char buffer[EVENT_BUF_LEN];

    fp = fopen(PATH, "r");
    if (fp == NULL)
            exit(EXIT_FAILURE);

    fd = fileno(fp);
    while (1)
    {
            read1 = getline(&line, &len, fp);
            if(read1 != -1)
                    printf("%s",line);
            else
            {
                    lseek(fd,0,SEEK_DATA);
            }
    }

    if (line)
            free(line);
    exit(EXIT_SUCCESS);
}

1 个答案:

答案 0 :(得分:4)

当您到达文件的第一个末尾时,将设置EOF的输入流标志。必须先清除它才能恢复操作(clearerr(fp))。你通常也应该睡觉。 (在与流关联的文件描述符上使用lseek()并不会有帮助。)

这是一个基于你的代码的程序 - 我不得不改变PATH的值(这不是一个特别好的名字):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define PATH "demo.txt"

int main(void)
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;

    fp = fopen(PATH, "r");
    if (fp == NULL)
    {
        perror(PATH);
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        if (getline(&line, &len, fp) != -1)
            printf("%s",line);
        else
        {
            printf("EOF\n");
            sleep(1);
            clearerr(fp);
        }
    }

    if (line)
        free(line);
    return(EXIT_SUCCESS);
}

如果您有一个为文件生成数据的程序,您可以使用它进行测试。我有一个程序dribbler可以做到这一点:

$ dribbler -f demo.txt -s 1.5 -r 0.5 &
[1] 20678
$ cat demo.txt
0: message written to file
1: message written to file
2: message written to file
$ tail11
0: message written to file
1: message written to file
2: message written to file
3: message written to file
4: message written to file
5: message written to file
EOF
6: message written to file
EOF
EOF
7: message written to file
EOF
8: message written to file
EOF
EOF
9: message written to file
EOF
10: message written to file
EOF
11: message written to file
EOF
EOF
^C
$

dribbler的选项是:

Usage: dribbler [-hlntV][-s nap.time][-r std.dev][-f outfile][-i infile][-m message][-o openstr][-F format]
  -V           Print version information and exit
  -f outfile   Write to named file (dribbler.out)
  -h           Print this help message and exit
  -i infile    Read lines from input file
  -l           Loop back to start of input file on EOF
  -m message   Write message on each line of output
  -n           Number lines read from input file
  -o openstr   Flags passed to fopen() (a+)
  -s nap.time  Sleep for given interval between writes (1.000 second)
  -r std.dev   Randomize the time (Gaussian around nap.time with std.dev)
  -t           Write to standard output instead of file
  -F format    Printf format to use instead of %zu

因此,它以1.5秒的平均时间写入文件demo.txt,具有0.5秒标准差的高斯随机分布。 这就是为什么在连续的输出行之间有时会出现2 EOF个混乱的原因。