Member Avatar for Member #728458

Hi all, I'm new to system programming. I wanted to read from a file into a buffer (say, buf[BUFSIZ]), from the end to the beginning. For example, if the file contains "Hello", then the buffer will contain "olleH". I know lseek() will reposition the opened file offset. I just tried lseek(fd, -6, 2), but the result is still "Hello". I don't know why. Please help, thank you very much!

Dani AI

Generated

A quick diagnosis: lseek only moves the file offset — it does not read or reverse bytes for you. In your case a call like lseek(fd, -6, SEEK_END) against a file containing "Hello" (5 bytes) attempts to set the offset to -1, which is invalid. lseek then fails (returns -1 and sets errno) and the file offset remains where it was, so your subsequent read returns the original contents. Always use the symbolic constants (SEEK_END) and check lseek's return value with perror/errno to catch that kind of error.

Two practical approaches that work well:

  • Read the whole file into memory and reverse it in place (simple and fast for files that fit in RAM):
struct stat st;
if (fstat(fd, &st) == -1) { perror("fstat"); /* handle */ }
off_t len = st.st_size;
char *buf = malloc(len);
if (!buf) { perror("malloc"); /* handle */ }
ssize_t got = read(fd, buf, len); /* loop until full read in production code */
for (off_t i = 0; i < len/2; ++i) {
    char t = buf[i];
    buf[i] = buf[len - 1 - i];
    buf[len - 1 - i] = t;
}
  • For very large files, use mmap() and iterate the mapped memory backwards without copying (memory‑efficient and fast):
char *m = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
/* check m != MAP_FAILED */
for (off_t i = len; i-- > 0; ) putchar(m[i]);
munmap(m, len);

As noted, repeatedly doing lseek+read byte-by-byte will work but is very slow because of system-call overhead; 's in-memory suggestion is generally the best balance for typical tasks. Final cautions: reversing bytes is not the same as reversing characters for UTF-8 or multibyte encodings (decode to codepoints first), and mmap isn’t available for non-regular files (pipes). Always check return values for lseek, read, mmap, etc., when troubleshooting.

Recommended Answers

All 2 Replies

Even though what you want to do makes no sense,

1- Use lseek() to get to the end of the file.
2- lseek() back one character
3- read the character
4- repeat 2&3 until you get to the beginning of the file

yeah, lseek doesnt read backwards. because seek doesnt read. seek just moves the file pointer to a relative position. lseek moves it to the "left" (ie, backwards)

file reads are always done in the forward sequence.

a better way to read something in reverse, is to first read it from the file as normal, into a character buffer in memory, then copy it backwards into your target buffer by decrementing the index or pointer.

walt's suggestion is very literal minded. Like the genie in the lamp granting wishes, he gave you exactly what you asked. it would be a huge resource hog for any sizeable file.


.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.