C rewind: Return a File Stream to the Beginning
To return a file stream to the beginning in C, use the rewind() function: rewind(fp); where fp is your FILE* pointer. It clears the error and end-of-file indicators and repositions the stream to its start, making it the simplest way to read a file again from the top.
Background: Why You Need to Rewind
In C, file streams are sequential by default. When you read from a file using functions like fgetc(), fgets(), or fread(), the stream’s internal position indicator moves forward. Once you reach the end, the end-of-file (EOF) flag is set, and further reads return failure. If you need to process the same file multiple times—for example, to count lines first and then extract data—you must reset the stream. Without a reset, the second pass would start at the end and immediately hit EOF.
The C standard library provides three main ways to reset a stream: rewind(), fseek(), and fsetpos(). Each has its own use cases, and understanding the differences helps you choose the right one for your situation.
How rewind() Works
rewind() is defined in <stdio.h> and has the signature:
void rewind(FILE *stream);
It performs two actions:
- Resets the file position indicator to the beginning of the file (byte offset 0).
- Clears the error indicator and the EOF flag for that stream.
Because it returns void, you cannot check for errors directly. If you need to know whether the reset succeeded, use fseek(stream, 0, SEEK_SET) instead, which returns 0 on success and non-zero on failure. However, for most practical purposes, rewind() is safe and sufficient.
Here’s a minimal example:
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) return 1;
// First pass: read and print all lines
char line[256];
while (fgets(line, sizeof(line), fp)) {
printf("%s", line);
}
// Rewind to the beginning
rewind(fp);
// Second pass: count lines
int count = 0;
while (fgets(line, sizeof(line), fp)) {
count++;
}
printf("Total lines: %d\n", count);
fclose(fp);
return 0;
}
Choosing Between rewind(), fseek(), and fsetpos()
All three functions can move the position indicator, but they differ in flexibility and error reporting:
- rewind() – Always goes to the start. No return value. Clears error flags. Best for simple “start over� scenarios.
- fseek() – Moves to any position using an offset from a reference point (
SEEK_SET,SEEK_CUR,SEEK_END). Returns 0 on success, non-zero on failure. Use it when you need to jump to a specific offset or when you want to check for errors. - fsetpos() – Moves to a position previously captured with
fgetpos(). Useful for large files where offsets may exceedlongrange (though on modern 64-bit systems,longis usually 64 bits, so this is rarely a concern). Returns 0 on success, non-zero on failure.
For simply returning to the beginning, rewind() is the most direct. If you want to verify success, use fseek(fp, 0, SEEK_SET).
Common Problems and Pitfalls
Here are the most frequent issues developers encounter when rewinding file streams:
- Not clearing EOF before reading again: If you just call
fseek()without clearing the EOF flag, the next read might still return EOF.rewind()clears it automatically, but if you usefseek(), you may need to callclearerr(fp)first. - Using rewind() on a stream opened in append mode: For streams opened with
"a"or"a+", writes are always appended to the end regardless of the position indicator. Rewinding has no effect on write operations. For reading,"a+"allows reading from the beginning after a rewind, but"a"does not allow reading at all. - Rewinding a non-seekable stream: Streams like pipes, sockets, or terminals are not seekable. Calling
rewind()on them is undefined behavior and will likely fail silently. Always check if the stream is seekable usingfseek(fp, 0, SEEK_CUR)and checking the return value. - Forgetting to close the file: If you rewind and then close the file, any buffered data is flushed. This is usually fine, but if you were writing, make sure you flush before rewinding to avoid data loss.
Comparison: rewind() vs. Closing and Reopening
An alternative to rewinding is to close the file and open it again. For example:
fclose(fp);
fp = fopen("data.txt", "r");
This works but has downsides:
- It’s slower because it involves system calls to close and open the file.
- It loses any buffered data and resets all stream state.
- If the file was opened with a specific mode (e.g., binary), you must remember to use the same mode again.
- If the file is a temporary file or has been deleted, reopening may fail.
Rewinding is almost always preferable when you need to read the same file again from the start.
Safety and Portability Considerations
rewind() is part of the C standard library (C89 and later), so it’s available on all conforming C compilers. It works with both text and binary streams, but there is a subtlety with text streams: on some platforms, the position indicator may not be a simple byte offset due to newline translation (e.g., Windows converts \n to \r\n). However, rewind() always returns to the beginning, so this is not an issue.
For binary streams, rewind() is equivalent to fseek(stream, 0, SEEK_SET). For text streams, it’s also equivalent, but the standard allows implementation-defined behavior for fseek() on text streams; rewind() is guaranteed to work.
One safety note: if you have multiple threads accessing the same file stream, rewinding is not thread-safe. You must synchronize access using locks (e.g., flockfile() and funlockfile()) or use separate file descriptors for each thread.
Frequently Asked Questions
Does rewind() work on stdin?
If stdin is a terminal or a pipe, it is not seekable, so rewind(stdin) will not work. However, if stdin is redirected from a regular file, it may work, but it’s not guaranteed by the standard. In practice, it’s best to avoid rewinding stdin unless you’re certain it’s a regular file.
What’s the difference between rewind() and fseek(fp, 0, SEEK_SET)?
Both set the position to the beginning. The main difference is that rewind() also clears the error and EOF indicators, while fseek() only clears EOF (according to the standard, a successful fseek() clears EOF, but not necessarily the error indicator). Also, fseek() returns an error code, while rewind() does not.
Can I rewind a file opened in append mode?
Yes, you can rewind a file opened in "a+" mode, and then read from the beginning. However, if you write after rewinding, the write will still go to the end of the file, not to the current position. For "a" mode, reading is not allowed at all.
Why does my second read still return EOF after rewind()?
If you called rewind() and still get EOF, the likely cause is that you are using a non-seekable stream, or you have a bug where you are not actually calling rewind() on the correct stream. Also, check that you didn’t close the file before the second read. Use clearerr(fp) after fseek() if you’re not using rewind().
Is rewind() safe for binary files?
Yes, rewind() is safe for binary files. It simply sets the position to the beginning. There is no issue with newline translation because binary mode does not translate newlines.
Does rewind() flush the buffer?
No, rewind() does not flush the output buffer. If you have been writing to the file, you should call fflush(fp) before rewinding to ensure all data is written to the underlying file. Otherwise, the buffered data may be written later, potentially overwriting what you read.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.