C fsetpos function
last modified April 6, 2025
File positioning is crucial for precise file operations in C programming. The
fsetpos function allows you to set the file position indicator to a
previously saved location. This tutorial explores fsetpos in depth,
explaining its usage with practical examples. You'll learn how to combine it with
fgetpos for reliable file navigation. Mastering these functions
enables efficient random access file operations in your C programs.
What Is fsetpos?
The fsetpos function sets the file position indicator for a stream
based on a position previously obtained with fgetpos. It takes a
FILE pointer and a pointer to a fpos_t object as
arguments. This function is particularly useful for large files where
ftell might not work correctly. Always check the return value for
errors. It returns zero on success and non-zero on failure.
Basic fsetpos Usage
This example demonstrates the fundamental usage of fsetpos to save
and restore a file position.
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
fpos_t position;
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Get current position
if (fgetpos(fp, &position) != 0) {
perror("Error getting position");
fclose(fp);
return 1;
}
// Read some data
char buffer[100];
fgets(buffer, sizeof(buffer), fp);
printf("First read: %s", buffer);
// Restore position
if (fsetpos(fp, &position) != 0) {
perror("Error setting position");
fclose(fp);
return 1;
}
// Read again from original position
fgets(buffer, sizeof(buffer), fp);
printf("Second read: %s", buffer);
fclose(fp);
return 0;
}
This code opens a file and saves the initial position using fgetpos.
After reading some data, it restores the position with fsetpos and
reads the same data again. The fpos_t type stores the position
information. Error checking is performed at each step to ensure proper operation.
Jumping to Specific Positions
Learn how to use fsetpos to jump to different positions in a file.
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
fpos_t positions[3];
char buffer[100];
int i;
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Store three different positions
for (i = 0; i < 3; i++) {
fgetpos(fp, &positions[i]);
fgets(buffer, sizeof(buffer), fp);
}
// Jump back to each position
for (i = 0; i < 3; i++) {
if (fsetpos(fp, &positions[i])) {
perror("Error setting position");
break;
}
fgets(buffer, sizeof(buffer), fp);
printf("Position %d: %s", i, buffer);
}
fclose(fp);
return 0;
}
This example stores three different file positions in an array of
fpos_t objects. Later, it jumps back to each position using
fsetpos and reads the data from those points. This technique is
useful when you need to revisit multiple specific locations in a file. The code
includes error handling for each position setting operation.
Working with Binary Files
See how fsetpos works with binary files for precise data access.
#include <stdio.h>
struct Record {
int id;
double value;
};
int main() {
FILE *fp = fopen("data.bin", "rb+");
fpos_t pos;
struct Record rec;
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Save position of second record
fseek(fp, sizeof(struct Record), SEEK_SET);
fgetpos(fp, &pos);
// Modify second record
rec.id = 999;
rec.value = 3.14159;
fwrite(&rec, sizeof(struct Record), 1, fp);
// Restore position and verify
fsetpos(fp, &pos);
fread(&rec, sizeof(struct Record), 1, fp);
printf("Record: id=%d, value=%f\n", rec.id, rec.value);
fclose(fp);
return 0;
}
This example demonstrates fsetpos with binary file operations. It
saves the position of the second record in a binary file, modifies it, then
restores the position to verify the change. The fpos_t variable
works seamlessly with binary files. This approach is ideal for database-like
operations where precise record access is required.
Error Handling with fsetpos
Proper error handling is essential when working with file positions. This example shows robust error checking.
#include <stdio.h>
#include <errno.h>
int main() {
FILE *fp = fopen("nonexistent.txt", "r");
fpos_t pos;
if (fp == NULL) {
perror("Initial open failed");
return 1;
}
// Try to get position from invalid file
if (fgetpos(fp, &pos) != 0) {
perror("fgetpos failed");
if (errno == EBADF) {
printf("File descriptor is invalid\n");
}
fclose(fp);
return 1;
}
// Try to set invalid position
if (fsetpos(fp, &pos) != 0) {
perror("fsetpos failed");
if (errno == EINVAL) {
printf("Invalid position specified\n");
}
}
fclose(fp);
return 0;
}
This code demonstrates comprehensive error handling for fsetpos and
related functions. It checks return values and examines errno for
specific error conditions. The example shows how to handle invalid file
descriptors and position values. Proper error handling makes your file operations
more reliable and easier to debug.
Large File Support
fsetpos is particularly useful for large files where
ftell might not work correctly.
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp = fopen("largefile.bin", "rb");
fpos_t pos;
long long file_size;
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Move to end to get file size
fseek(fp, 0, SEEK_END);
fgetpos(fp, &pos);
// Convert fpos_t to byte offset (platform-specific)
// Note: This is just for demonstration - not portable
file_size = *(long long *)&pos;
printf("File size: %lld bytes\n", file_size);
// Jump to middle of file
fseek(fp, file_size/2, SEEK_SET);
fgetpos(fp, &pos);
// Process data from middle of file
char buffer[1024];
fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
return 0;
}
This example shows how fsetpos can handle positions in very large
files. While the conversion of fpos_t to a numeric value is
platform-specific, it demonstrates the concept. For truly portable code, use
fgetpos and fsetpos without interpreting the
fpos_t contents. This approach works reliably regardless of file
size.
Combining with fgetpos
fsetpos is typically used with fgetpos to save and
restore positions.
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
fpos_t start_pos, end_pos;
char buffer[100];
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Mark start position
fgetpos(fp, &start_pos);
// Read until empty line
while (fgets(buffer, sizeof(buffer), fp)) {
if (buffer[0] == '\n') {
fgetpos(fp, &end_pos);
break;
}
}
// Process from start to empty line
fsetpos(fp, &start_pos);
while (fgetpos(fp, &start_pos), start_pos < end_pos) {
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
}
fclose(fp);
return 0;
}
This example shows a practical use case for fgetpos and
fsetpos together. It marks the start position, reads until an empty
line, marks that position, then processes the section between the two positions.
This pattern is useful for processing file segments. The positions are compared
using their internal representation.
Text vs Binary Mode Considerations
Understand how text and binary modes affect fsetpos behavior.
#include <stdio.h>
int main() {
FILE *fp_text = fopen("text.txt", "r");
FILE *fp_bin = fopen("text.txt", "rb");
fpos_t pos_text, pos_bin;
char ch;
if (!fp_text || !fp_bin) {
perror("Error opening files");
return 1;
}
// Read first character in text mode
ch = fgetc(fp_text);
fgetpos(fp_text, &pos_text);
// Read first character in binary mode
ch = fgetc(fp_bin);
fgetpos(fp_bin, &pos_bin);
// Compare positions
printf("Text mode position: %p\n", (void *)&pos_text);
printf("Binary mode position: %p\n", (void *)&pos_bin);
// Attempt cross-mode position setting (may fail)
if (fsetpos(fp_text, &pos_bin) != 0) {
printf("Cannot set text mode stream with binary position\n");
}
fclose(fp_text);
fclose(fp_bin);
return 0;
}
This example demonstrates that positions obtained in text mode may not be compatible with binary mode streams and vice versa. The code opens the same file in both modes, gets positions, and shows they're different. Attempting to use a binary mode position in a text mode stream typically fails. Always use positions with the same stream they were obtained from.
Best Practices for Using fsetpos
- Always check return values: Both
fgetposandfsetposreturn zero on success. - Use with same stream: Positions are only valid for the stream they were obtained from.
- Combine with fgetpos: Typically used together to save and restore positions.
- Prefer for large files: More reliable than
ftell/fseekfor files > 2GB. - Consider platform differences:
fpos_timplementation varies across systems.
Source
This tutorial has explored the fsetpos function in C, demonstrating
its use for precise file positioning. From basic usage to advanced scenarios with
large files, these examples provide a solid foundation for file handling in your
C programs.
Author
List C Standard Library.