C++: عمليات الملفات المتقدمة
آخر تحديث: 2026-08-26
في الدرس 40 تعلمنا معالجة الاستثناءات.
الآن، سنتعمق في عمليات الملفات - مهارة أساسية للبيانات الدائمة في البرامج.
سواء كانت ملفات تهيئة أو سجلات أو قواعد بيانات، عمليات الملفات ضرورية.
1. نظرة عامة على تدفقات الملفات
(1) 1.1 فئات تدفق الملفات الثلاث
تستخدم C++ ثلاث فئات للتعامل مع الملفات:
| الفئة | الغرض |
|---|---|
std::ifstream |
تدفق ملف إدخال (قراءة الملفات) |
std::ofstream |
تدفق ملف إخراج (كتابة الملفات) |
std::fstream |
تدفق ملف إدخال/إخراج (قراءة وكتابة) |
(2) 1.2 فتح ملف
مثال: فتح ملف (الصعوبة ⭐)
▶ مثال 2: عرض عمليات الملف (الصعوبة ⭐)
#include <iostream>
#include <fstream>
int main() {
std::ifstream file("data.txt");
if (!file) {
std::cerr << "Unable to open file" << std::endl;
return 1;
}
std::cout << "File opened successfully" << std::endl;
file.close();
return 0;
}
الخرج:
File opened successfully
2. قراءة وكتابة الملفات النصية
(1) 2.1 القراءة سطراً بسطر
مثال: عد أسطر الملف (الصعوبة ⭐)
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream file("data.txt");
std::string line;
int count = 0;
while (std::getline(file, line)) {
count++;
}
std::cout << "Number of lines: " << count << std::endl;
file.close();
return 0;
}
(2) 2.2 القراءة والكتابة المنسقتان
مثال: قراءة وكتابة بنية (الصعوبة ⭐⭐)
#include <iostream>
#include <fstream>
struct Student {
char name[50];
int age;
double score;
};
int main() {
Student s = {"Zhang San", 20, 85.5};
// الكتابة إلى ملف
std::ofstream out("student.txt");
out << s.name << std::endl;
out << s.age << std::endl;
out << s.score << std::endl;
out.close();
// القراءة من ملف
Student s2;
std::ifstream in("student.txt");
in >> s2.name >> s2.age >> s2.score;
in.close();
std::cout << "Name: " << s2.name << std::endl;
std::cout << "Age: " << s2.age << std::endl;
std::cout << "Score: " << s2.score << std::endl;
return 0;
}
⚠️ تحذير:
- هذه الطريقة لا تعمل بشكل جيد مع الأسماء التي تحتوي على مسافات (
>>تتوقف عند المسافات البيضاء)
3. الملفات الثنائية
(1) 3.1 لماذا نستخدم الملفات الثنائية؟
| المقارنة | ملف نصي | ملف ثنائي |
|---|---|---|
| قابلية القراءة | مقروء بشرياً | غير مقروء |
| الحجم | أكبر | صغير |
| السرعة | أبطأ | سريع |
| عبر المنصات | جيد | ضعيف (مشاكل ترتيب البايتات) |
(2) 3.2 قراءة وكتابة الملفات الثنائية
مثال: قراءة/كتابة ثنائية لبنية (الصعوبة ⭐⭐⭐)
#include <iostream>
#include <fstream>
struct Student {
char name[50];
int age;
double score;
};
int main() {
Student s = {"Zhang San", 20, 85.5};
// كتابة ملف ثنائي
std::ofstream out("student.bin", std::ios::binary);
out.write(reinterpret_cast<char*>(&s), sizeof(s));
out.close();
// قراءة ملف ثنائي
Student s2;
std::ifstream in("student.bin", std::ios::binary);
in.read(reinterpret_cast<char*>(&s2), sizeof(s2));
in.close();
std::cout << "Name: " << s2.name << std::endl;
std::cout << "Age: " << s2.age << std::endl;
std::cout << "Score: " << s2.score << std::endl;
return 0;
}
💡 نصيحة:
- استخدم
writeوreadللإدخال/الإخراج الثنائي - يجب تحديد عدد البايتات (
sizeof)
4. الوصول العشوائي
(1) 4.1 seekg و seekp
الوصول العشوائي يسمح لك بالقفز إلى أي موضع في الملف للقراءة أو الكتابة.
| الدالة | الغرض |
|---|---|
seekg(pos) |
تعيين موضع القراءة |
seekp(pos) |
تعيين موضع الكتابة |
tellg() |
الحصول على موضع القراءة الحالي |
tellp() |
الحصول على موضع الكتابة الحالي |
(2) 4.2 مثال: تعديل المحتوى في وسط الملف (الصعوبة ⭐⭐⭐)
#include <iostream>
#include <fstream>
int main() {
std::fstream file("data.txt", std::ios::in | std::ios::out);
// القفز إلى البايت العاشر
file.seekp(10);
// كتابة بيانات (الكتابة فوق)
file << "Hello";
file.close();
return 0;
}
الخرج:
Hello, File!
C++ File Operations
5. حالة تدفق الملف
(1) 5.1 أعلام الحالة
لتدفقات الملفات 4 أعلام حالة:
| العلم | الوصف |
|---|---|
good() |
كل شيء على ما يرام |
eof() |
الوصول إلى نهاية الملف |
fail() |
خطأ منطقي (مثلاً عدم تطابق النوع) |
bad() |
خطأ جسيم (مثلاً فشل القرص) |
(2) 5.2 مسح الحالة
مثال: معالجة نهاية الملف (الصعوبة ⭐)
#include <iostream>
#include <fstream>
int main() {
std::ifstream file("data.txt");
std::string line;
while (true) {
std::getline(file, line);
if (file.eof()) {
break; // الوصول إلى نهاية الملف
}
std::cout << line << std::endl;
}
file.clear(); // مسح الحالة للاستمرار في الاستخدام
file.close();
return 0;
}
6. تطبيق: قاعدة بيانات بسيطة
▶ مثال 1: إدارة سجلات الطلاب (الصعوبة ⭐⭐⭐)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
struct Student {
int id;
char name[50];
int age;
};
void saveStudents(const std::vectorStudent& students, const std::string& filename) {
std::ofstream file(filename, std::ios::binary);
for (const auto& s : students) {
file.write(reinterpret_cast<const char*>(&s), sizeof(s));
}
}
void loadStudents(std::vectorStudent& students, const std::string& filename) {
std::ifstream file(filename, std::ios::binary);
Student s;
while (file.read(reinterpret_cast<char*>(&s), sizeof(s))) {
students.push_back(s);
}
}
int main() {
std::vector<Student> students = {
{1, "Zhang San", 20},
{2, "Li Si", 21}
};
// حفظ
saveStudents(students, "students.bin");
// تحميل
std::vectorStudent loaded;
loadStudents(loaded, "students.bin");
std::cout << "Loaded " << loaded.size() << " records" << std::endl;
return 0;
}
الخرج:
Loaded 2 records
▶ مثال 3: قراءة/كتابة ملف بسيط (الصعوبة ⭐)
#include <iostream>
#include <fstream>
#include <string>
int main() {
// الكتابة إلى ملف
std::ofstream outFile("test.txt");
outFile << "Hello, File!" << std::endl;
outFile << "C++ File Operations" << std::endl;
outFile.close();
// القراءة من ملف
std::ifstream inFile("test.txt");
std::string line;
while (std::getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
return 0;
}
الخرج:
(program output)
الخرج المتوقع:
Hello, File!
C++ File Operations
❓ أسئلة شائعة
if (!file)، مع معالجة الاستثناءات.📖 ملخص
| الموضوع | النقاط الأساسية |
|---|---|
| فئات تدفق الملفات | ifstream/ofstream/fstream |
| الملفات النصية | العاملان << و >> |
| الملفات الثنائية | write و read |
| الوصول العشوائي | seekg/seekp |
| التحقق من الحالة | eof()/fail()/bad() |
📝 تمارين
-
أساسي (الصعوبة ⭐): استخدم
ofstreamلكتابة ملف نصي (ثلاثة أسطر من المحتوى)، ثم استخدمifstreamلقراءته وعرضه على الشاشة. -
متوسط (الصعوبة ⭐⭐): استخدم
fstreamلفتح ملف بوضعios::binary، اكتب مصفوفة من البنى، ثم اقرأها وتحقق منها. -
متقدم (الصعوبة ⭐⭐⭐): استخدم
seekg/tellgلتطبيق وصول عشوائي للملفات. أنشئ "ملف فهرس" يسجل موضع كل سجل، مع دعم القفز المباشر إلى سجل محدد بالفهرس.
- تدفقات الملفات: ifstream للقراءة / ofstream للكتابة / fstream لكليهما
- أوضاع الفتح: in/out/app/binary/trunc
- التحقق من حالة الملف: is_open/good/fail/eof
- الملفات النصية مقابل الثنائية: النصي مقروء لكن أبطأ
- الوصول العشوائي: seekg/tellg لتحديد مواضع القراءة/الكتابة
الدرس التالي: التعابير النمطية (#42)