← Back to C Course | Chapter 10: File I/O | Lesson 5 of 6

C fseek() & ftell()

Random access using fseek()

SEEK_SET seeks relative to the file's beginning, SEEK_CUR relative to the current position, and SEEK_END relative to the end -- this flexibility lets you jump anywhere in a file without reading through everything before it.

Example: Random access using fseek()

c
#include <stdio.h>
int main() {
	FILE *fp = fopen("data.txt", "w");
	fprintf(fp, "0123456789");
	fclose(fp);
	fp = fopen("data.txt", "r");
	fseek(fp, 5, SEEK_SET);
	char c = fgetc(fp);
	fclose(fp);
	printf("%c", c);
	return 0;
}

Finding positions with ftell()

Combining ftell() before and after an operation lets you measure exactly how many bytes a particular read or write consumed, which is useful for building custom file indexes or verifying I/O behavior.

Example: Finding positions with ftell()

c
#include <stdio.h>
int main() {
	FILE *fp = fopen("data.txt", "w");
	fprintf(fp, "Hello");
	long pos = ftell(fp);
	fclose(fp);
	printf("%ld", pos);
	return 0;
}

Rewinding streams with rewind()

This is functionally identical to fseek(fp, 0, SEEK_SET) but is more concise and self-documenting when all you want is to restart reading a file from its beginning.

Example: Rewinding streams with rewind()

c
#include <stdio.h>
int main() {
	FILE *fp = fopen("data.txt", "w");
	fprintf(fp, "Hello");
	fclose(fp);
	fp = fopen("data.txt", "r");
	fgetc(fp);
	rewind(fp);
	char c = fgetc(fp);
	fclose(fp);
	printf("%c", c);
	return 0;
}

Calculating file size

The common pattern is fseek(fp, 0, SEEK_END) followed by long size = ftell(fp), then fseek(fp, 0, SEEK_SET) to return to the start before actually reading the data -- this three-step dance is a very common idiom in C file handling.

Example: Calculating file size

c
#include <stdio.h>
int main() {
	FILE *fp = fopen("data.txt", "w");
	fprintf(fp, "Hello");
	fclose(fp);
	fp = fopen("data.txt", "r");
	fseek(fp, 0, SEEK_END);
	long size = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	fclose(fp);
	printf("%ld", size);
	return 0;
}

Moving from EOF using SEEK_END

Negative offsets combined with SEEK_END are the standard way to read a file's last N bytes without reading through the entire file first, which matters for performance on very large files.

Example: Moving from EOF using SEEK_END

c
#include <stdio.h>
int main() {
	FILE *fp = fopen("data.txt", "w");
	fprintf(fp, "0123456789");
	fclose(fp);
	fp = fopen("data.txt", "r");
	fseek(fp, -3, SEEK_END);
	char c = fgetc(fp);
	fclose(fp);
	printf("%c", c);
	return 0;
}
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.