- Open a file to read
- Read all the lines until EOF
- After 5 seconds, another contents are appended to the file
- Is it possible to read the newly written lines only until EOF again?
4 Answers
You can clear the error and EOF indicators after reading EOF by using clearerr() or fseek(). You then have to decide how you are going to stop; maybe because of an unhandled signal (interrupt, etc). That leads to code like:
#include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: %s file\n", argv[0]); return 1; } FILE *fp = fopen(argv[1], "r"); if (fp == 0) { fprintf(stderr, "%s: failed to open file '%s' for reading\n", argv[0], argv[1]); return 1; } while (1) { char buffer[4096]; while (fgets(buffer, sizeof(buffer), fp) != 0) fputs(buffer, stdout); clearerr(fp); // fseek(fp, 0L, SEEK_CUR); sleep(5); } /*NOTREACHED*/ return 0; } Note that I wrote this as C code. However, it also compiles cleanly with a C++ compiler (even when it is set to be fussy).
$ g++ -O3 -g -std=c++11 -Wall -Wextra -Werror tf17.cpp -o tf17 $ gcc -O3 -g -std=c11 -Wall -Wextra -Werror tf19.c -o tf19 $ It was tested with a home-brew program called dribbler that writes messages slowly to a file.
Note that if you use fseek() to clear the EOF state, it is a good idea to seek zero bytes offset from the current position (SEEK_CUR). If you seek to the end, you might skip over data written since the program detected EOF. You could still run into problems if the file was truncated while you were reading it. The current position might be beyond the end of the truncated file.
3 Comments
This should work :
#include <stdio.h> #include <unistd.h>//To use the sleep function under UNIX int main(void) { FILE *f; int i; char line[1024]; f = fopen("yourfile", "r"); i = 0; while(fgets(line, 1024, f) != NULL) { //You can use your line here i++; //'i' is the number of line } fclose(f); sleep(5);//This line may change on windows f = fopen("yourfile", "r");//Reopen your file after modification while(i != 0)//We skip the line we already used { fgets(line, 1024, f); i--; } while(fgets(line, 1024, f) != NULL)//Here are the new line { //You can use your new line here } fclose(f); return 0; } 4 Comments
you can count the rows that you have already read and after 5 seconds you can read from next line.
void GotoLine(std::fstream& file, unsigned int num){ file.seekg(std::ios::beg); for(int i=0; i < num - 1; ++i){ file.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); } string line; file>>line; cout<<line<<endl; //printing the new line data } Comments
There are some points that can help in reading from a file while it is actively being written to :-
- You can use mmap() with MAP_SHARED in both reader and writer. This way the reader will see the changes done by the writer practically immediately.
- Linux does not make any snapshot of the data in the file when you open the file, so you should see the changes that are being made in the file even if you just use read() and lseek().
- In order to determine whether a file was modified/opened/accessed/etc in Linux you can use inotify API. This allows you to make your process wait for an event you're interested in until it occurs (as opposed to polling it regularly).
- tail(), to find a tail of a file.
A small snippet can work for you: here in this example we are reading and writing at the same time.
read_pos = write_pos = 0; while ((val1 = fgetc(file_descriptor)) != EOF) { read_pos = ftell(file_descriptor); fseek(file_descriptor, write_pos, SEEK_SET); if (('a' <= val1) && (val1 <= 'z')) { fputc(val1 - 32, file_descriptor); } else { fputc(val1, file_descriptor); } write_pos = ftell(file_descriptor); fseek(file_descriptor, read_pos, SEEK_SET); } fclose(file_descriptor); return (0); } }
clearerr()?sleep()? Are you usingcinand<iostream>etc? Or are you using<stdio.h>? Or<cstdio>?