مقدمة: لماذا العمل مع نظام الملفات في C++ هو الأساس
\n\nأي برنامج جاد عاجلاً أم آجلاً سيواجه الحاجة إلى حفظ البيانات على القرص أو قراءتها منه. ملفات التكوين، السجلات، قواعد البيانات، المستندات الخاصة بالمستخدم - كل هذا يتطلب القدرة على التفاعل مع نظام الملفات. في لغة C++، هناك طريقتان رئيسيتان لذلك: تدفقات الإدخال/الإخراج الكلاسيكية (مكتبة <fstream>) والطريقة الحديثة ذات المستوى الأعلى std::filesystem (بدءًا من C++17).
في هذه المقالة، سنستعرض السيناريوهات العملية: من القراءة والكتابة البسيطة للملفات النصية إلى التنقل بين المجلدات ومعالجة الأخطاء. جميع الأمثلة مكتوبة بلغة C++17/20 وجاهزة للاستخدام في مشاريعك.
\n\n1. الأساسيات: قراءة وكتابة الملفات باستخدام fstream
\n\nتوفر مكتبة <fstream> ثلاث فئات رئيسية: ifstream (تيار الإدخال - القراءة)، ofstream (تيار الإخراج - الكتابة)، و fstream (تيار ثنائي الاتجاه). دعنا نستعرضها من خلال الأمثلة.
1.1. الكتابة في ملف نصي
\n\nأبسط طريقة لكتابة البيانات هي استخدام ofstream. إذا لم يكن الملف موجودًا، فسيتم إنشاؤه. إذا كان موجودًا، فسيتم استبداله (الوضع الافتراضي ios::trunc).
#include <iostream>\n#include <fstream>\n#include <string>\n\nint main() {\n std::ofstream outFile("example.txt");\n if (!outFile) {\n std::cerr << "خطأ في فتح الملف للكتابة\\n";\n return 1;\n }\n\n outFile << "مرحبًا، نظام ملفات C++!\\n";\n outFile << "السطر رقم 2\\n";\n outFile << 42 << " — هذا رقم.\\n";\n\n outFile.close(); // الإغلاق اليدوي ليس ضروريًا ولكنه أسلوب جيد\n std::cout << "تم كتابة البيانات.\\n";\n return 0;\n}\n\n1.2. القراءة من ملف نصي
\n\nللقراءة نستخدم ifstream. الطريقة الأكثر موثوقية هي القراءة سطرًا بسطر عبر std::getline.
#include <iostream>\n#include <fstream>\n#include <string>\n\nint main() {\n std::ifstream inFile("example.txt");\n if (!inFile) {\n std::cerr << "الملف غير موجود أو لا يمكن فتحه\\n";\n return 1;\n }\n\n std::string line;\n while (std::getline(inFile, line)) {\n std::cout << "تمت القراءة: " << line << '\\n';\n }\n\n inFile.close();\n return 0;\n}\n\n1.3. أوضاع الفتح والملفات الثنائية
\n\nيمكنك دمج علامات الفتح: ios::app (إلحاق)، ios::binary (الوضع الثنائي)، ios::ate (الانتقال إلى النهاية). للملفات الثنائية، استخدم الطريقتين read() و write().
#include <fstream>\n#include <vector>\n\n// مثال: كتابة وقراءة متجه من الأرقام بالتنسيق الثنائي\nvoid saveVector(const std::string& filename, const std::vector<int>& data) {\n std::ofstream file(filename, std::ios::binary);\n if (!file) return;\n file.write(reinterpret_cast<const char*>(data.data()), data.size() * sizeof(int));\n}\n\nstd::vector<int> loadVector(const std::string& filename) {\n std::ifstream file(filename, std::ios::binary);\n if (!file) return {};\n file.seekg(0, std::ios::end);\n size_t size = file.tellg() / sizeof(int);\n file.seekg(0, std::ios::beg);\n std::vector<int> data(size);\n file.read(reinterpret_cast<char*>(data.data()), size * sizeof(int));\n return data;\n}\n\n2. النهج الحديث: std::filesystem (C++17)
\n\nبدءًا من C++17، تم تضمين وحدة <filesystem> في المكتبة القياسية، والتي تتيح العمل مع المسارات والملفات والمجلدات على مستوى عالٍ وبشكل متعدد المنصات.
2.1. التحقق من الوجود والحصول على معلومات حول الملف
\n\nالمزيد