File Handling
Opening, reading from, writing to, and closing files in C. Using functions like `fopen`, `fclose`, `fread`, `fwrite`, `fprintf`, and `fscanf`.
File Positioning in C: fseek, ftell, and rewind
In C programming, file positioning functions allow you to move the file pointer to different locations within a file. This is essential for reading or writing data at specific points and enables more flexible file access than sequential reading or writing alone. The primary functions for file positioning are fseek
, ftell
, and rewind
.
fseek: Moving the File Pointer
The fseek
function is used to move the file pointer to a specified location within a file. Its syntax is:
int fseek(FILE *stream, long int offset, int whence);
stream
: A pointer to theFILE
object associated with the open file.offset
: The number of bytes to move the file pointer. This can be positive (forward), negative (backward), or zero.whence
: Specifies the reference point from which the offset is applied. It can be one of the following macros:SEEK_SET
: Beginning of the file. The offset is relative to the start of the file.SEEK_CUR
: Current position of the file pointer. The offset is relative to the current position.SEEK_END
: End of the file. The offset is relative to the end of the file. Note that using a positive offset withSEEK_END
is undefined behavior.
fseek
returns 0 on success and a non-zero value on failure (e.g., attempting to seek beyond the file boundaries). It's crucial to check the return value of fseek
to ensure the operation was successful.
Example: Moving to the beginning of the 10th record (assuming each record is 50 bytes):
#include <stdio.h>
int main() {
FILE *fp;
long int offset;
int record_size = 50; // Size of each record in bytes
int record_number = 10; // Accessing the 10th record
fp = fopen("data.txt", "r"); // Open the file in read mode
if (fp == NULL) {
perror("Error opening file");
return 1;
}
offset = (record_number - 1) * record_size; // Calculate the offset
if (fseek(fp, offset, SEEK_SET) == 0) {
printf("Successfully moved to the beginning of the %dth record.\n", record_number);
// Now you can read the data from the 10th record
char buffer[record_size + 1]; // +1 for null terminator if you're reading strings
if (fread(buffer, 1, record_size, fp) == record_size) {
buffer[record_size] = '\\0'; // Null-terminate the string if you expect a string
printf("Data read: %s\n", buffer);
} else {
perror("Error reading record");
}
} else {
perror("Error seeking in file");
}
fclose(fp);
return 0;
}
ftell: Determining the File Pointer Position
The ftell
function returns the current position of the file pointer in bytes, relative to the beginning of the file. Its syntax is:
long int ftell(FILE *stream);
ftell
returns the current file pointer position as a long int
or -1L
on error. This is useful for saving the current position and returning to it later.
Example: Getting the current file pointer position after reading some data:
#include <stdio.h>
int main() {
FILE *fp;
long int position;
char buffer[20];
fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Read some data
fread(buffer, 1, 10, fp);
buffer[10] = '\\0';
printf("Read data: %s\n", buffer);
// Get the current file pointer position
position = ftell(fp);
if (position != -1L) {
printf("Current file pointer position: %ld bytes\n", position);
} else {
perror("Error getting file position");
}
fclose(fp);
return 0;
}
rewind: Resetting the File Pointer
The rewind
function sets the file pointer to the beginning of the file. Its syntax is:
void rewind(FILE *stream);
rewind
does not return a value. It is equivalent to calling fseek(stream, 0, SEEK_SET)
, except that it also clears the error and end-of-file indicators for the stream.
Example: Rewinding the file pointer after reading some data:
#include <stdio.h>
int main() {
FILE *fp;
char buffer1[20], buffer2[20];
fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
// Read some data
fread(buffer1, 1, 10, fp);
buffer1[10] = '\\0';
printf("First read: %s\n", buffer1);
// Rewind the file pointer
rewind(fp);
// Read the same data again (from the beginning)
fread(buffer2, 1, 10, fp);
buffer2[10] = '\\0';
printf("Second read (after rewind): %s\n", buffer2);
fclose(fp);
return 0;
}
Accessing Specific Records or Sections
The power of fseek
, ftell
, and rewind
lies in their ability to access specific parts of a file. Combining these allows for features like random access to records in a database file or parsing specific sections of a configuration file. Remember to handle error conditions and carefully calculate offsets based on your data structure and file format.