无法读取 C 中过去的 EOF

问题描述 投票:0回答:1

本质上是一个

tail -f
实现:我正在更新一个在旧系统上运行良好的程序,它将连续读取打开的文件:在EOF之后,等待文件增长并继续读取。在较新的系统上,它无法读取 EOF 之后的文件,我不明白为什么。我删除了所有不相关的代码,并能够使用以下简化示例进行重现,该示例与此处给出的模式几乎相同

// COMPILE WITH: gcc a.c -o a.out #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> int main(int argc, char* argv[]) { //---------------------------------------------------------------- char* file_path = "/var/log/mail.log"; // any file that's active int seek_to_head = 0; int seek_to_tail = 1; int loop_sleep_seconds = 4; int use_getline = 1; // if 0, uses fgets() //---------------------------------------------------------------- size_t line_size_fgets = 1024; char line_fgets[line_size_fgets]; char* line = NULL; size_t line_size = 0; // Open the file FILE* FILE_HANDLE; if (!(FILE_HANDLE = fopen(file_path, "r"))) { printf("Failed to open file [%s]: %s\n", file_path, strerror(errno)); return 1; } // Unbuffer input if (setvbuf(FILE_HANDLE, NULL, _IONBF, 0) != 0) // if (setvbuf(FILE_HANDLE, NULL, _IOLBF, 0) != 0) { printf("Failed to unbuffer\n"); return 1; } // Seek to head if (seek_to_head) { if (fseek(FILE_HANDLE, 0, SEEK_SET)) { printf("Failed to seek to beginning of file\n"); return 1; } printf("Seek to start of file -- SUCCESS\n"); } // Seek to tail if (seek_to_tail) { if (fseek(FILE_HANDLE, 0, SEEK_END)) { printf("Failed to seek to end of file\n"); return 1; } printf("Seek to end of file -- SUCCESS\n"); } printf("Begin tracking file %s\n", file_path); // Main loop while (1) { // Read all remaining file contents til exhausted for now if (use_getline) while (getline(&line, &line_size, FILE_HANDLE) != -1) printf("\nLINE: %s\n", line); else while (fgets(line_fgets, line_size_fgets, FILE_HANDLE) != NULL) printf("\nLINE: %s\n", line_fgets); // Make sure there wasn't an error reading file if (ferror(FILE_HANDLE)) { printf("Failed to read from file [%s]: %s\n", file_path, strerror(errno)); return 1; } // Pause for file to grow (inotify code goes here) sleep(loop_sleep_seconds); printf("Try reading again\n"); } free(line); printf("Exiting\n"); return 0; }
此示例有一个变量,您可以翻转以使用 getline() 或 fgets(),但在我尝试过的较新系统上,两者都存在相同的问题。如果查找文件的开头,则会打印迄今为止的所有文件内容,但不会打印此后的任何内容。如果查找到文件末尾,则不会产生任何输出。真正的程序轮询文件更改而不是休眠,我确认轮询工作正常,但这似乎无关;两种方式的错误行为都是相同的。

我错过了一些明显的东西吗?

c fgets eof getline
1个回答
0
投票
您可以(并且应该)在尝试读取更多数据之前显式清除 EOF。比如:

// Pause for file to grow (inotify code goes here) if( feof( FILE_HANDLE ) ) { clearerr( FILE_HANDLE ) ; sleep(loop_sleep_seconds); printf("Try reading again\n"); }
否则 EOF 通常只能通过调用

同一流上的 rewind、fseek、fsetpos 和 freopen 之一来清除。因此您可以选择 或 setpos

 到当前位置。

© www.soinside.com 2019 - 2024. All rights reserved.