I'm trying to read a file backwards (say 10 lines at the end of the file). I would increment my new line counter (newline_counter
) everytime it reads a '\n'. Once newline_counter
reaches user_num
(argument), say 10 lines, lseek()
would stop at the current position (current_pos
). I'm returning this position so that I can use this position in another function which uses lseek()
to this position and start reading from this position and write until the end of the file. I have successfully compiled the program but once I start to run it, the program just keeps running and there is no output.
int func_line_mode(int infile, int user_num) {
char c;
int newline_counter = 0;
int current_pos = 0;
int end = lseek(infile, 0, SEEK_END);
int counter = 0;
while (counter < end || newline_counter <= user_num) {
lseek(infile, current_pos, SEEK_END);
read(infile, &c, sizeof(char));
if (strcmp(&c,"\n") == 0) {
newline_counter++;
}
current_pos--;
counter++;
}
return current_pos;
}
Some problems with your code:
The while
condition is wrong, it should be:
while (counter < end && newline_counter <= user_num)
After the while
, you are left one byte before the last newline, so you should go forward 2 bytes to be precise:
if (current_pos < 0)
current_pos += 2;
lseek()
returns an off_t
, not int
, so you should do:
off_t end = lseek(infile, 0, SEEK_END);
As a consequence, other variables that you use to do comparisons should be off_t
too, and most importantly the return type of the function too.
strcmp(&c,"\n")
is wrong, to compare a single character you can just do c == '\n'
.
Number 1 is probably the reason of your problem. Other points should be fixed too, specially number 4.
Once all of the above is fixed, the function correctly works for me. Here's a working example:
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
off_t func_line_mode(int infile, int user_num) {
char c;
int newline_counter = 0;
off_t current_pos = 0;
off_t end = lseek(infile, 0, SEEK_END);
off_t counter = 0;
while (counter < end && newline_counter < user_num) {
lseek(infile, current_pos, SEEK_END);
read(infile, &c, 1);
if (c == '\n')
newline_counter++;
current_pos--;
counter++;
}
if (current_pos < 0)
current_pos += 2;
return current_pos;
}
int main() {
char buf[100];
int nread, nwrite;
int fd = open("test.txt", O_RDONLY);
// Last 3 lines.
off_t off = func_line_mode(fd, 3);
printf("off = %d\n", off);
// Go back.
lseek(fd, off, SEEK_END);
while (nread = read(fd, buf, 100)) {
nwrite = 0;
while (nwrite < nread)
nwrite += write(1, buf + nwrite, nread - nwrite);
}
return 0;
}