File I/O — Text, Binary, Random Access

ফাইলসিস্টেমের সাথে কথোপকথন

~35 min Intermediate 12 practice problems Live code

1. Files as Streams

C-তে প্রতিটি ফাইল একটি FILE * stream-এর মাধ্যমে access করা হয়। fopen দিয়ে খুলে, fclose দিয়ে বন্ধ করতে হয়।

FILE *f = fopen("data.txt", "r");
if (!f) { perror("fopen"); return 1; }

// ... use f ...

fclose(f);
fopen ব্যর্থ হলে NULL ফেরত দেয়। Cause জানতে perror বা strerror(errno) ব্যবহার করুন।

2. Open Modes

ModeMeaning
"r"Read — file অবশ্যই থাকতে হবে
"w"Write — না থাকলে তৈরি হয়, থাকলে truncate
"a"Append — শেষে লেখা, না থাকলে তৈরি
"r+"Read + write (file থাকতে হবে)
"w+"Write + read (truncate)
"rb", "wb", …Binary mode (Windows-এ গুরুত্বপূর্ণ)

3. Reading Line by Line

Online runner-এ সাধারণত ফাইল তৈরি করা যায় না, তাই এই demo stdin থেকে পড়ছে — কিন্তু pattern হুবহু একই, শুধু stdin-এর জায়গায় FILE * বসালেই হয়।

readlines.c — stdin acts as the file
#include <stdio.h>

int main(void) {
    FILE *f = stdin;          // in real code: fopen("data.txt", "r")
    char line[1024];
    int n = 0;
    while (fgets(line, sizeof line, f)) {
        printf("%3d | %s", ++n, line);
    }
    printf("(total %d lines)\n", n);
    return 0;
}

4. Writing and Reading — End-to-End Demo

নিচের প্রোগ্রামটি একটি temporary file-এ লিখে, বন্ধ করে, আবার খুলে পড়ে — পুরো cycle এক জায়গায়।

roundtrip.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    const char *path = "notes.txt";

    // 1) write
    FILE *w = fopen(path, "w");
    if (!w) { perror("open for write"); return 1; }
    fprintf(w, "Hello, Bangladesh!\n");
    fprintf(w, "Line 2, with a number %d\n", 42);
    fclose(w);

    // 2) read back
    FILE *r = fopen(path, "r");
    if (!r) { perror("open for read"); return 1; }
    char line[256];
    while (fgets(line, sizeof line, r)) fputs(line, stdout);
    fclose(r);

    remove(path);              // clean up the temp file
    return 0;
}

5. Binary I/O — fread / fwrite

typedef struct { char name[32]; int id; double gpa; } Student;

Student arr[100];
fwrite(arr, sizeof arr[0], n, f);    // write n records
fread(arr, sizeof arr[0], n, f);     // read them back
Binary I/O-তে আপনি বাস্তবে যে bytes আছে সেগুলোই লিখেন/পড়েন — কোনো text formatting নেই। ফলে দ্রুত, কিন্তু file-এর content cross-platform পড়তে হলে endianness ও struct padding-এর যত্ন নিতে হয়।

6. Random Access — fseek & ftell

fseek(f, 0, SEEK_END);          // go to the end
long size = ftell(f);            // file size in bytes
rewind(f);                       // back to the start
fseek(f, 100, SEEK_SET);         // absolute offset 100
fseek(f, -10, SEEK_CUR);         // 10 bytes backwards

7. Error Handling

#include <errno.h>

FILE *f = fopen("nope.txt", "r");
if (!f) {
    fprintf(stderr, "open failed: %s\n", strerror(errno));
    perror("context");    // prints "context: No such file or directory"
    return 1;
}

প্রতিটি I/O function-এর return value যাচাই করুন। fgets NULL দিলে হয় EOF, না হয় read error — ferror(f) আর feof(f) দিয়ে পার্থক্য করা যায়।

8. Practice Problems

  1. Copy one file to another byte-by-byte.
    একটি file অপরটিতে byte-by-byte কপি করুন।
    ✨ Show Answer
    fcopy.c
    #include <stdio.h>
    
    int main(void) {
        const char *src = "a.txt", *dst = "b.txt";
        FILE *in = fopen(src, "wb");
        fputs("ABCL TECH", in); fclose(in);
    
        in  = fopen(src, "rb");
        FILE *out = fopen(dst, "wb");
        int c;
        while ((c = fgetc(in)) != EOF) fputc(c, out);
        fclose(in); fclose(out);
    
        // print result
        out = fopen(dst, "r");
        char buf[64] = {0};
        fread(buf, 1, 63, out);
        puts(buf);
        fclose(out);
        remove(src); remove(dst);
        return 0;
    }
  2. Count lines in a file.
    একটি file-এ লাইন সংখ্যা গুনুন।
    ✨ Show Answer
    count_lines.c
    #include <stdio.h>
    int main(void) {
        const char *p = "sample.txt";
        FILE *w = fopen(p, "w");
        fputs("first\nsecond\nthird\n", w);
        fclose(w);
    
        FILE *r = fopen(p, "r");
        int n = 0, c;
        while ((c = fgetc(r)) != EOF) if (c == '\n') n++;
        fclose(r);
        printf("lines = %d\n", n);
        remove(p);
        return 0;
    }
  3. Count occurrences of a word in a file.
    একটি file-এ একটি নির্দিষ্ট শব্দ কতবার আছে গুনুন।
    ✨ Show Answer
    count_word.c
    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        const char *p = "essay.txt", *needle = "C";
        FILE *w = fopen(p, "w");
        fputs("I love C. C is fun. Systems need C.\n", w);
        fclose(w);
    
        FILE *f = fopen(p, "r");
        char line[512]; int total = 0;
        while (fgets(line, sizeof line, f)) {
            char *q = line;
            while ((q = strstr(q, needle))) { total++; q += strlen(needle); }
        }
        fclose(f);
        printf(""%s" appears %d times\n", needle, total);
        remove(p);
        return 0;
    }
  4. Append a log entry to a file on each run.
    প্রতিবার প্রোগ্রাম চালালে একটি log entry file-এ append হবে।
    ✨ Show Answer
    append_log.c
    #include <stdio.h>
    #include <time.h>
    
    int main(void) {
        const char *p = "app.log";
    
        FILE *f = fopen(p, "a");          // append
        fprintf(f, "run at time %ld\n", (long)time(NULL));
        fclose(f);
    
        // show contents
        f = fopen(p, "r");
        char line[256];
        while (fgets(line, sizeof line, f)) fputs(line, stdout);
        fclose(f);
        remove(p);
        return 0;
    }
  5. Read integers from a file into an array, then print sorted.
    File থেকে integer পড়ে array-তে রাখুন, তারপর sort করে প্রিন্ট করুন।
    ✨ Show Answer
    sort_file.c
    #include <stdio.h>
    #include <stdlib.h>
    int cmp(const void *a, const void *b) { return *(const int*)a - *(const int*)b; }
    int main(void) {
        const char *p = "nums.txt";
        FILE *w = fopen(p, "w");
        fputs("42 7 19 3 88 21 56 11", w);
        fclose(w);
    
        FILE *r = fopen(p, "r");
        int a[100], n = 0;
        while (n < 100 && fscanf(r, "%d", &a[n]) == 1) n++;
        fclose(r);
        qsort(a, n, sizeof *a, cmp);
        for (int i = 0; i < n; i++) printf("%d ", a[i]);
        putchar('\n');
        remove(p);
        return 0;
    }
  6. Save an array of Students to a binary file and read it back.
    Student array-কে binary file-এ save করে আবার পড়ুন।
    ✨ Show Answer
    students_bin.c
    #include <stdio.h>
    #include <string.h>
    
    typedef struct { char name[32]; int id; double gpa; } Student;
    
    int main(void) {
        const char *p = "students.dat";
        Student a[3] = { {"Arif",101,3.72}, {"Nusrat",102,3.92}, {"Zahid",103,3.55} };
    
        FILE *w = fopen(p, "wb");
        fwrite(a, sizeof a[0], 3, w);
        fclose(w);
    
        Student b[3] = {0};
        FILE *r = fopen(p, "rb");
        fread(b, sizeof b[0], 3, r);
        fclose(r);
    
        for (int i = 0; i < 3; i++)
            printf("%s  id=%d  gpa=%.2f\n", b[i].name, b[i].id, b[i].gpa);
        remove(p);
        return 0;
    }
  7. Implement tail -n — print the last N lines of a file.
    tail -n-এর মতো file-এর শেষ N লাইন প্রিন্ট করুন।
    ✨ Show Answer
    tail_n.c
    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        const char *p = "sample.txt";
        FILE *w = fopen(p, "w");
        for (int i = 1; i <= 10; i++) fprintf(w, "line %d\n", i);
        fclose(w);
    
        const int N = 3;
        char buf[N][256] = {{0}};
        FILE *r = fopen(p, "r");
        int count = 0;
        char line[256];
        while (fgets(line, sizeof line, r)) {
            strncpy(buf[count % N], line, 255);
            count++;
        }
        fclose(r);
    
        int start = count >= N ? count % N : 0;
        int shown = count < N ? count : N;
        for (int i = 0; i < shown; i++)
            fputs(buf[(start + i) % N], stdout);
        remove(p);
        return 0;
    }
  8. Compute the size of a file without reading its contents.
    Content না পড়েই একটি file-এর size বের করুন।
    ✨ Show Answer
    filesize.c
    #include <stdio.h>
    
    int main(void) {
        const char *p = "big.bin";
        FILE *w = fopen(p, "wb");
        char pad[100] = {0};
        fwrite(pad, 1, 100, w);
        fclose(w);
    
        FILE *f = fopen(p, "rb");
        fseek(f, 0, SEEK_END);
        printf("size = %ld bytes\n", ftell(f));
        fclose(f);
        remove(p);
        return 0;
    }
  9. Find and replace all occurrences of one word in a text file.
    একটি text file-এর সব জায়গায় একটি word-কে অন্যটি দিয়ে replace করুন।
    ✨ Show Answer

    সহজ approach: পুরো ফাইল memory-তে পড়ুন, একটি নতুন buffer-এ find/replace করে write করুন। Large file হলে line-by-line process করুন।

    replace.c
    #include <stdio.h>
    #include <string.h>
    
    void process_line(const char *src, const char *find, const char *repl, FILE *out) {
        size_t fl = strlen(find);
        const char *p = src, *q;
        while ((q = strstr(p, find))) {
            fwrite(p, 1, q - p, out);
            fputs(repl, out);
            p = q + fl;
        }
        fputs(p, out);
    }
    
    int main(void) {
        const char *in_p = "in.txt", *out_p = "out.txt";
        FILE *w = fopen(in_p, "w");
        fputs("C is fun. C makes systems go.\n", w); fclose(w);
    
        FILE *r = fopen(in_p, "r");
        FILE *o = fopen(out_p, "w");
        char line[1024];
        while (fgets(line, sizeof line, r)) process_line(line, "C", "ABCL TECH", o);
        fclose(r); fclose(o);
    
        FILE *s = fopen(out_p, "r");
        while (fgets(line, sizeof line, s)) fputs(line, stdout);
        fclose(s);
        remove(in_p); remove(out_p);
        return 0;
    }
  10. Concatenate multiple files (Unix cat).
    একাধিক file concatenate করুন (cat-এর মতো)।
    ✨ Show Answer
    cat_many.c
    #include <stdio.h>
    
    void cat_one(const char *p) {
        FILE *f = fopen(p, "r");
        if (!f) { perror(p); return; }
        int c; while ((c = fgetc(f)) != EOF) fputc(c, stdout);
        fclose(f);
    }
    
    int main(void) {
        // seed two sample files
        FILE *w = fopen("a.txt", "w"); fputs("first\n",  w); fclose(w);
        w = fopen("b.txt", "w");        fputs("second\n", w); fclose(w);
    
        const char *files[] = { "a.txt", "b.txt" };
        for (int i = 0; i < 2; i++) cat_one(files[i]);
    
        remove("a.txt"); remove("b.txt");
        return 0;
    }
  11. Build a tiny fixed-size-record database using fseek.
    fseek দিয়ে ছোট fixed-record DB বানান।
    ✨ Show Answer
    tiny_db.c
    #include <stdio.h>
    #include <string.h>
    
    typedef struct { int id; char name[32]; } Rec;
    
    int main(void) {
        const char *db = "mini.db";
        FILE *f = fopen(db, "wb+");
        Rec a = { 1, "Alice" }, b = { 2, "Bob" };
        fwrite(&a, sizeof a, 1, f);
        fwrite(&b, sizeof b, 1, f);
    
        // seek to record #1 (0-indexed) and read it
        fseek(f, 1 * sizeof(Rec), SEEK_SET);
        Rec r; fread(&r, sizeof r, 1, f);
        printf("rec[1] = id=%d name=%s\n", r.id, r.name);
        fclose(f);
        remove(db);
        return 0;
    }
  12. Why do you need "rb" on Windows but not on Linux?
    Windows-এ "rb" কেন দরকার, Linux-এ কেন নয়?
    ✨ Show Answer

    Windows-এর text mode read/write করার সময় \r\n-কে \n-এ রূপান্তর করে দেয় (এবং লেখার সময় উল্টোটা)। Binary ডেটার জন্য এটি বিপর্যয়কর — একটি 0x0D byte হারিয়ে যেতে পারে। "rb" / "wb" দিলে সেই auto-translation বন্ধ থাকে। Linux/macOS-এ text ও binary একই — তাই পার্থক্য নেই। তবু portable কোডে সবসময় "rb"/"wb" লিখুন।

Glossary (শব্দকোষ)

TermMeaningবাংলায়
FILE *Opaque pointer representing an open file/stream.খোলা file/stream-এর pointer।
fopenOpens a file and returns a FILE *.File খুলে FILE * ফেরত দেয়।
fcloseFlushes buffers and closes the file.Buffer flush করে file বন্ধ করে।
Mode String"r", "w", "a", "rb", "wb" — open semantics.File খোলার পদ্ধতি বর্ণনাকারী string।
Text ModeNewlines may be translated by the platform.Platform অনুযায়ী newline রূপান্তর হয়।
Binary ModeReads/writes bytes verbatim.Byte যেমন আছে তেমনই read/write হয়।
fread / fwriteBlock read/write of binary records.Binary record read/write করা।
fprintf / fscanfFormatted I/O on a file stream.File stream-এ formatted I/O।
fgetsReads a line of text up to a size limit.Size সীমাসহ এক লাইন পড়া।
fseek / ftellMove/get the file position for random access.Random access-এর জন্য position সরানো/পড়া।
rewindResets file position to the beginning.Position শুরুতে ফিরিয়ে আনা।
EOFEnd-of-file indicator returned by read functions."ফাইল শেষ" নির্দেশক।
ferror / perrorInspect / print stream errors.Stream error যাচাই/print করা।

Summary — Module 20

Open, check, read/write, close। fgets text line-এর জন্য, fread/fwrite binary record-এর জন্য, fseek random access-এর জন্য। প্রতিটি কাজের error check করুন — perror বা ferror।

Next Module → Preprocessor & Macros।