๐ What is a File Pointer?
In C, whenever we open a file using fopen(), we get back a file pointer โ an internal handler used to track the current position in the file.
FILE *fp = fopen("myfile.txt", "r");This
fppoints to the beginning of the file when it's opened in read mode.As you read or write, the pointer moves automatically.
Think of it like a cursor in a text editor:
It starts at the top,
moves with each character/line read or written,
and you can manually move it using special functions.
๐ Why do we need to control the file pointer?
๐ Reread a specific part of the file
โฉ Skip unnecessary data
๐ฆ Append new data at specific positions
๐ Jump to a specific record in a binary file
๐ Reset file pointer to reprocess content
๐ fseek() โ Move the File Pointer
fseek() is used to manually move the file pointer to a specific location within a file. This is especially useful when you want to skip over certain parts of the file or jump directly to a known position for reading or writing. It provides flexibility for random access instead of just sequential reading or writing.
๐ง Syntax:
int fseek(FILE *fp, long offset, int origin);๐ Parameter | ๐ Description |
|---|---|
| File pointer |
| Number of bytes to move (positive or negative) |
| Reference point for movement |
๐ฏ Values for origin:
๐น Macro | ๐ Meaning |
|---|---|
| Beginning of file |
| Current position |
| End of file |
โ Example 1: Move to the 10th byte from start
fseek(fp, 10, SEEK_SET); // Moves pointer to byte 10 (zero-based)โ Example 2: Move 5 bytes forward from current
fseek(fp, 5, SEEK_CUR);โ Example 3: Go 20 bytes before the end
fseek(fp, -20, SEEK_END);โ ๏ธ Notes:
fseek()returns0on success andnon-zeroon failure.offsetis in bytes, so it's exact, unlike skipping characters or lines.
๐ ftell() โ Get Current Position of File Pointer
ftell() returns the current position of the file pointer, measured in bytes from the beginning of the file. It's helpful when you need to know where you are in the fileโsuch as for tracking progress or for returning to that location later.
๐ง Syntax:
long position = ftell(fp);Returns the current byte offset from the beginning of the file.
Very useful for:
Logging position
Creating bookmarks in files
Debugging or offset calculations
โ Example:
FILE *fp = fopen("sample.txt", "r");
fseek(fp, 15, SEEK_SET);
long pos = ftell(fp);
printf("Current position: %ld\\n", pos); // Output: 15๐ rewind() โ Reset Pointer to Beginning
rewind(fp); // Equivalent to fseek(fp, 0, SEEK_SET);Doesnโt return any value
Resets error and EOF flags too
๐ Complete Example โ Using fseek(), ftell(), and rewind()
๐ Content of demo.txt
Welcome to CodeVeda!Each character (including spaces) is 1 byte.
Position 10 โ "Welcome to " โ the 11th character is 'C'.
#include <stdio.h>
int main() {
// Open the file in read mode
FILE *fp = fopen("demo.txt", "r");
if (fp == NULL) {
printf("File error.\\n");
return 1;
}
// Move the file pointer to the 10th byte from the beginning
fseek(fp, 10, SEEK_SET); // 'C' of "CodeVeda"
printf("Position after fseek: %ld\\n", ftell(fp)); // Should print 10
// Read the character at the 10th byte position
char ch = fgetc(fp);
printf("Character at position 10: %c\\n", ch); // Should print 'C'
// Rewind resets the file pointer back to the beginning
rewind(fp);
printf("Position after rewind: %ld\\n", ftell(fp)); // Should print 0
fclose(fp); // Close the file
return 0;
}<div class="infographic-cseek">
<style>
.infographic-cseek {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--code-bg: #1e1e2e;
--code-text: #d4d4e0;
--syn-func: #dcdcaa;
}
.infographic-cseek[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--code-bg: #0d0d14;
--code-text: #d4d4e0;
}
.infographic-cseek {
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', -apple-system, sans-serif;
padding: 0 clamp(1rem, 4vw, 2.25rem) 1.25rem;
}
.infographic-cseek *, .infographic-cseek *::before, .infographic-cseek *::after {
box-sizing: border-box;
}
.infographic-cseek h1 {
font-family: 'Fraunces', Georgia, serif;
font-weight: 600;
font-size: clamp(1.3rem, 3.5vw, 1.7rem);
margin: 1.25rem 0 0.2rem;
text-align: center;
}
.infographic-cseek .subhead { color: var(--ink-soft); font-size: 0.85rem; margin-bottom: 1.2rem; text-align: center; }
.infographic-cseek .file-strip { display: flex; gap: 0.18rem; justify-content: center; flex-wrap: wrap; margin-bottom: 0.3rem; }
.infographic-cseek .ch-cell { text-align: center; }
.infographic-cseek .ch-box {
width: 1.6rem;
height: 1.9rem;
display: flex;
align-items: center;
justify-content: center;
border: 1.5px solid var(--line);
border-radius: 4px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.78rem;
font-weight: 700;
background: var(--paper-alt);
color: var(--ink-soft);
transition: border-color 0.2s, background 0.2s, color 0.2s;
}
.infographic-cseek .ch-box.is-read { opacity: 0.4; }
.infographic-cseek .ch-idx { font-family: 'IBM Plex Mono', monospace; font-size: 0.55rem; color: var(--ink-soft); margin-top: 0.1rem; }
.infographic-cseek .cursor-marker { text-align: center; font-size: 0.8rem; color: var(--accent); height: 1rem; margin-bottom: 0.2rem; visibility: hidden; }
.infographic-cseek .ch-cell.is-cursor .ch-box { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.infographic-cseek .strip-wrap { position: relative; margin-bottom: 1.1rem; }
.infographic-cseek .strip-cols { display: flex; gap: 0.18rem; justify-content: center; flex-wrap: wrap; }
.infographic-cseek .status-row {
text-align: center;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.85rem;
color: var(--accent);
font-weight: 700;
margin-bottom: 1rem;
}
.infographic-cseek .field-row { display: flex; align-items: center; justify-content: center; gap: 0.5rem; margin-bottom: 0.7rem; flex-wrap: wrap; }
.infographic-cseek .field-row label { font-family: 'IBM Plex Mono', monospace; font-size: 0.8rem; color: var(--ink-soft); }
.infographic-cseek .field-row input {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.85rem;
padding: 0.3rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
width: 3.6rem;
}
.infographic-cseek .act-btn {
all: unset; cursor: pointer;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.78rem; font-weight: 600;
padding: 0.4rem 0.8rem;
border-radius: 999px;
background: var(--accent);
color: #fff;
}
.infographic-cseek .act-btn:hover { opacity: 0.88; }
.infographic-cseek .act-btn.secondary { background: var(--paper-alt); color: var(--ink); border: 1px solid var(--line); }
.infographic-cseek .result-panel {
text-align: center;
padding: 0.6rem 0.9rem;
background: var(--paper-alt);
border-radius: 8px;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.85rem;
color: var(--ink-soft);
min-height: 2.2rem;
}
.infographic-cseek .result-panel strong { color: var(--accent); }
.infographic-cseek .takeaway {
font-size: 0.82rem; color: var(--ink-soft);
margin-top: 1.3rem; border-top: 1px solid var(--line); padding-top: 0.9rem;
}
.infographic-cseek .takeaway strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-cseek * { transition: none !important; }
}
</style>
<h1>๐ fseek ยท ftell ยท rewind</h1>
<p class="subhead">demo.txt = "HelloWorldCodeVeda" โ move the cursor around it.</p>
<div class="strip-wrap">
<div class="cursor-marker" id="cursor-marker">โผ</div>
<div class="strip-cols" id="file-strip"></div>
</div>
<div class="status-row">ftell(fp) = <span id="ftell-val">0</span></div>
<div class="field-row">
<label>fseek(fp,</label><input type="number" id="seek-offset" value="10">
<label>, SEEK_SET)</label>
</div>
<div class="field-row">
<button class="act-btn" id="btn-seek">โถ fseek()</button>
<button class="act-btn secondary" id="btn-getc">โถ fgetc()</button>
<button class="act-btn secondary" id="btn-rewind">โถ rewind()</button>
</div>
<div class="result-panel" id="result-panel">Nothing read yet.</div>
<p class="takeaway"><strong>rewind(fp)</strong> is just a shortcut for <code style="font-family:'IBM Plex Mono',monospace;">fseek(fp, 0, SEEK_SET)</code> โ jump straight back to the start.</p>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-cseek')
|| document.querySelector('.infographic-cseek');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function $(sel) { return wrapper.querySelector(sel); }
const CONTENT = 'HelloWorldCodeVeda';
const strip = $('#file-strip');
const marker = $('#cursor-marker');
const ftellVal = $('#ftell-val');
const seekOffset = $('#seek-offset');
const resultPanel = $('#result-panel');
let pos = 0;
const cells = [];
CONTENT.split('').forEach((ch, i) => {
const cell = document.createElement('div');
cell.className = 'ch-cell';
cell.innerHTML = '<div class="ch-box">' + ch + '</div><div class="ch-idx">' + i + '</div>';
strip.appendChild(cell);
cells.push(cell);
});
function render() {
ftellVal.textContent = pos;
cells.forEach((c, i) => c.classList.toggle('is-cursor', i === pos));
marker.style.visibility = pos < CONTENT.length ? 'visible' : 'hidden';
if (pos < CONTENT.length) {
const cellRect = cells[pos].getBoundingClientRect();
const wrapRect = marker.parentElement.getBoundingClientRect();
marker.style.position = 'relative';
marker.style.left = (cellRect.left - wrapRect.left - marker.offsetWidth / 2 + cellRect.width / 2) + 'px';
}
}
$('#btn-seek').addEventListener('click', () => {
let n = parseInt(seekOffset.value, 10) || 0;
n = Math.max(0, Math.min(CONTENT.length, n));
seekOffset.value = n;
pos = n;
resultPanel.innerHTML = 'Cursor moved to position <strong>' + n + '</strong>.';
render();
});
$('#btn-getc').addEventListener('click', () => {
if (pos >= CONTENT.length) {
resultPanel.textContent = 'End of file โ nothing left to read.';
return;
}
const ch = CONTENT[pos];
cells[pos].querySelector('.ch-box').classList.add('is-read');
resultPanel.innerHTML = "fgetc(fp) returned '<strong>" + ch + "</strong>' โ cursor moves to " + (pos + 1) + '.';
pos++;
render();
});
$('#btn-rewind').addEventListener('click', () => {
pos = 0;
resultPanel.innerHTML = 'rewind(fp) โ cursor back to <strong>0</strong>.';
render();
});
render();
window.addEventListener('resize', render);
})();
</script>โ Common Mistakes to Avoid
โ ๏ธ Mistake | ๐ Why it matters |
|---|---|
Not checking return value of | It may silently fail if file is too small |
Using | Causes undefined behavior |
Misusing | Especially on Windows, due to newline encoding differences |
Assuming | It may not behave as expected due to newline translation |
๐ Use Cases of File Pointer Manipulation
๐ Reading a specific record in a fixed-size database file
๐ Resetting file to beginning without reopening
๐งฎ Finding file size:
๐ Content of textfile.txt
Name: CodeVeda
Age: 25
This is a simple line.โ Code:
#include <stdio.h>
int main() {
FILE *fp = fopen("textfile.txt", "r");
if (fp == NULL) {
printf("Error opening file.\\n");
return 1;
}
fseek(fp, 0, SEEK_END); // Move to end of file
long size = ftell(fp); // Get the current file position (size in bytes)
rewind(fp); // Go back to beginning of file
printf("File size: %ld bytes\\n", size);
fclose(fp);
return 0;
}File size: 50 bytes