C: read only the last line of the file. No cycles

With C, is there a way to read only the last line of a file without looping it over all the content?

The thing is that the file contains millions strings, each of which contains an integer (long long int). The file itself can be quite large, I suppose, even up to 1000mb. I know for sure that the last line will not be longer than 55 digits, but there may be 2 digits. Of the options to use any database ... I have already considered this.

This may be a dumb question, but based on PHP, it's hard for me to answer. I searched everywhere but found nothing.

I am currently using:

if ((fd = fopen(filename, "r")) != NULL) // open file { fseek(fd, 0, SEEK_SET); // make sure start from 0 while(!feof(fd)) { memset(buff, 0x00, buff_len); // clean buffer fscanf(fd, "%[^\n]\n", buff); // read file *prefer using fscanf } printf("Last Line :: %d\n", atoi(buff)); // for testing I'm using small integers } 

Thus, I loop the contents of the file, and as soon as the file becomes larger than ~ 500 thousand lines, the situation gets much worse ...

Thanks in advance. Maksim

+6
source share
4 answers

If there is a maximum line length, find this distance to the end. Read to the end and find the last end of the line in your buffer.

If there is no maximum line length, guess a reasonable value, read it at the end, and if there is no end of the line, double your guess and try again.

In your case:

 /* max length including newline */ static const long max_len = 55 + 1; /* space for all of that plus a nul terminator */ char buf[max_len + 1]; /* now read that many bytes from the end of the file */ fseek(fd, -max_len, SEEK_END); ssize_t len = read(fd, buf, max_len); /* don't forget the nul terminator */ buf[len] = '\0'; /* and find the last newline character (there must be one, right?) */ char *last_newline = strrchr(buf, '\n'); char *last_line = last_newline+1; 
+5
source

Just fseek to fileSize - 55 and read ahead?

+6
source

Open "rb" to make sure you are reading the binary. Then fseek(..., SEEK_END) and start reading bytes from the back until you find the first line separator (if you know that the maximum line length is 55 characters, read 55 characters ...).

+3
source

OK. It all worked for me. I learned something new. The last line of the file is 41 MB long and> 500 thousand. The lines were read instantly. Thank you to all the guys, especially "Useless" (like arguing about your nickname, by the way). I will post the code here in the hope that someone in the future can benefit from this:

Only ONLY the last line of the file:

the file is structured so that a new line is added, and I am sure that any line is shorter than in my case, 55 characters:

 file contents: ------------------------ 2943728727 3129123555 3743778 412912777 43127787727 472977827 ------------------------ 

note the new line added.

 FILE *fd; // File pointer char filename[] = "file.dat"; // file to read static const long max_len = 55+ 1; // define the max length of the line to read char buff[max_len + 1]; // define the buffer and allocate the length if ((fd = fopen(filename, "rb")) != NULL) { // open file. I omit error checks fseek(fd, -max_len, SEEK_END); // set pointer to the end of file minus the length you need. Presumably there can be more than one new line caracter fread(buff, max_len-1, 1, fd); // read the contents of the file starting from where fseek() positioned us fclose(fd); // close the file buff[max_len-1] = '\0'; // close the string char *last_newline = strrchr(buff, '\n'); // find last occurrence of newlinw char *last_line = last_newline+1; // jump to it printf("captured: [%s]\n", last_line); // captured: [472977827] } 

Hurrah! Maksim

+1
source

All Articles