التعامل مع الملفات (File Handling) في C++

🎯 أولًا: لماذا التعامل مع الملفات مهم؟

قبل ما نكتب سطر كود… لازم تعرف “ليش” نتعامل مع ملفات أساسًا؟

✔ 1. التخزين الدائم (Persistent Storage)

الذاكرة RAM تتصفر عند إغلاق البرنامج.
الملفات تعيش.

✔ 2. مشاركة البيانات

  • برنامج يقرأ بيانات من ملف JSON
  • تطبيق يقرأ إعدادات config
  • سجل مستخدمين login stored locally
  • Logs لحفظ الأخطاء

✔ 3. التعامل مع Big Data

ما تقدر تحمل 1GB بالذاكرة…
لكن تقدر تقرأه على دفعات من ملف.

✔ 4. إنشاء قواعد بيانات مصغرة

قبل ما تتعامل مع MySQL و SQLite…
لازم تفهم File Handling.

✔ 5. Binary Processing

قراءة الصور، الفيديو، الصوت…
كلها ملفات ثنائية.

إذن…
هذا الدرس مش درس “إضافي” —
هو درس أساسي للحياة البرمجية.

────────────────────────────────────────────

🧱 ثانيًا: المكتبة الأساسية — fstream

المكتبة الرئيسية:

#include <fstream>

وتوفر 3 أنواع:

النوعالوظيفة
ifstreamللقراءة من الملفات
ofstreamللكتابة إلى الملفات
fstreamللقراءة والكتابة معًا

بإمكانك استخدام أي نوع حسب الهدف.

────────────────────────────────────────────

📝 ثالثًا: أنواع الملفات

هناك نوعين رئيسيين للتعامل في C++:

1️⃣ الملفات النصية (Text Files)

ملفات عادية تقرأها بالبشر:

hello
age 20
mark 99.5

2️⃣ الملفات الثنائية (Binary Files)

غير قابلة للقراءة بالبشر:

%#&%1011100101???Δ♥

تُقرأ فقط بواسطة برامج.

الملفات الثنائية ضرورية لتخزين Struct، الصور، أو البيانات الثقيلة.

────────────────────────────────────────────

🧨 رابعًا: فتح ملف نصي للكتابة — ofstream

أول خطوة:

ofstream file("data.txt");

✔ كتابة البيانات في الملف

file << "مرحباً محمد\n";
file << "هذا درس كود التطور.\n";

✔ لا تنسَ الإغلاق

file.close();

📌 ملاحظة:

لو الملف غير موجود، سيتم إنشاءه تلقائيًا.


🔥 مثال كامل:

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ofstream file("notes.txt");

    if (!file) {
        cout << "فشل فتح الملف!" << endl;
        return 1;
    }

    file << "درس التعامل مع الملفات\n";
    file << "نكتب الآن داخل ملف نصي.\n";

    file.close();
}

🧹 خامسًا: قراءة ملف نصي — ifstream

الطريقة الذهبية:

ifstream file("notes.txt");
string line;

while (getline(file, line)) {
    cout << line << endl;
}

✔ لماذا getline وليس file >> ؟

لأنه:

  • يحافظ على الفراغات
  • يقرأ السطر كامل
  • مناسب للملفات النصية

🔥 مثال كامل:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream file("notes.txt");
    string line;

    if (!file) {
        cout << "لا يمكن فتح الملف!" << endl;
        return 1;
    }

    while (getline(file, line)) {
        cout << line << endl;
    }

    file.close();
}

♻️ سادسًا: القراءة والكتابة في نفس الوقت — fstream

fstream file("log.txt", ios::in | ios::out | ios::app);

📝 شرح الأوضاع (File Modes):

الوضعالمعنى
ios::inللقراءة
ios::outللكتابة
ios::appيكتب في نهاية الملف
ios::truncيحذف المحتوى القديم
ios::binaryيفتح الملف ثنائي

🔒 سابعًا: التحقق من فتح الملف

ضروري جدًا:

if (!file) {
    cout << "خطأ في فتح الملف" << endl;
}

🧬 ثامنًا: الملفات الثنائية (Binary Files)

هنا ندخل إلى المستوى الحقيقي.
الملفات الثنائية تعمل مع Struct، كائنات، أرقام… بصيغة Bytes خام.


⭐ الكتابة إلى ملف Binary — write()

file.write((char*)&variable, sizeof(variable));

⭐ القراءة من ملف Binary — read()

file.read((char*)&variable, sizeof(variable));

🎯 مثال كبير: كتابة وقراءة أرقام

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ofstream out("nums.bin", ios::binary);
    int x = 10, y = 20, z = 30;

    out.write((char*)&x, sizeof(x));
    out.write((char*)&y, sizeof(y));
    out.write((char*)&z, sizeof(z));
    out.close();

    ifstream in("nums.bin", ios::binary);
    int a, b, c;

    in.read((char*)&a, sizeof(a));
    in.read((char*)&b, sizeof(b));
    in.read((char*)&c, sizeof(c));

    cout << a << " " << b << " " << c << endl;
}

📤 النتيجة:

10 20 30

🧱 تاسعًا: Binary + Struct = قوة مذهلة

⭐ كتابة Struct داخل Binary File

struct Student {
    int id;
    char name[50];
    double grade;
};
Student s = {1, "Mohammad", 95.5};

ofstream file("students.bin", ios::binary);
file.write((char*)&s, sizeof(s));
file.close();

⭐ قراءة Struct:

Student s;

ifstream file("students.bin", ios::binary);
file.read((char*)&s, sizeof(s));
file.close();

cout << s.id << " " << s.name << " " << s.grade;

🛠 عاشرًا: التعامل مع ملف فيه العديد من الـ Struct

Student temp;

ifstream file("students.bin", ios::binary);
while (file.read((char*)&temp, sizeof(temp))) {
    cout << temp.id << " " << temp.name << " " << temp.grade << endl;
}

⚠️ الحادي عشر: أخطر الأخطاء التي تحدث في File Handling

❌ 1. نسيان close()

قد يسبب:

  • ضياع البيانات
  • عدم حفظ التعديلات

❌ 2. استخدام read/write للملفات النصية

يغطي على محتوى الملف.

❌ 3. تغيير حجم struct بعد الكتابة

يؤدي إلى تلف البيانات!

❌ 4. تخزين pointer داخل ملف

كارثة…
العنوان يتغير عند كل تشغيل.

❌ 5. نسيان ios::binary

يجعل الملف “مكسورًا” حرفيًا.


🧠 الثاني عشر: مقارنة Text vs Binary بالتفصيل

جانب المقارنةTextBinary
قابل للقراءة البشرية
الحجمأكبرأصغر
السرعةأبطأأسرع
الاستخدامإعدادات – LogsStruct – صور – ألعاب – قواعد بيانات
الدقةمنخفضةدقيقة جدًا

📦 الثالث عشر: مشروع عملي واقعي — نظام إدارة طلاب كامل باستخدام Binary

🔹 تعريف Struct

struct Student {
    int id;
    char name[50];
    double grade;
};

🔹 إضافة طالب

void addStudent(Student s) {
    ofstream file("students.dat", ios::binary | ios::app);
    file.write((char*)&s, sizeof(s));
    file.close();
}

🔹 عرض جميع الطلاب

void showAll() {
    Student s;
    ifstream file("students.dat", ios::binary);
    while (file.read((char*)&s, sizeof(s))) {
        cout << s.id << " " << s.name << " " << s.grade << endl;
    }
}

🔹 البحث عن طالب

bool findStudent(int target) {
    Student s;
    ifstream file("students.dat", ios::binary);
    while (file.read((char*)&s, sizeof(s))) {
        if (s.id == target) {
            cout << "Found: " << s.name << endl;
            return true;
        }
    }
    return false;
}

مشروع كامل يعمل بشكل كامل على File Handling.


🔥 الرابع عشر: تقنيات احترافية (Professional Techniques)

✔ 1. استخدام seekg و seekp

للتنقل داخل الملف:

file.seekg(0, ios::beg); // بداية الملف
file.seekg(0, ios::end); // نهايته

✔ 2. حساب حجم الملف

file.seekg(0, ios::end);
int size = file.tellg();

✔ 3. القراءة على شكل Chunks

لملفات ضخمة جدًا (GBs).

✔ 4. فتح ملفات Binary بدون Overwrite

fstream file("data.bin", ios::in | ios::out | ios::binary);

🎯 الخلاصة النهائية

ملفّات C++ ليست درسًا عابرًا…
هي الأساس اللي بصير بفضله برنامجك يعيش بعد إغلاقه.

وفي هذا الدرس تعلّمت:
✔ التعامل الكامل مع الملفات النصية
✔ الكتابة والقراءة والتحكم الكامل
✔ التعامل مع الملفات الثنائية (Binary)
✔ تخزين Struct خارج الذاكرة
✔ مشروع كامل واقعي
✔ أخطاء قاتلة يجب تجنبها
✔ تقنيات احترافية للملفات الكبيرة

هذا درس “كود التطور” الحقيقي…
واقعي، طويل، كبير، احترافي، مليان محتوى قابل للاستخدام الفوري.


اكتشاف المزيد من كود التطور

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك رد

Scroll to Top