البرمجة

تعلم التعامل مع الملفات في C++

دخل وخرج الملفات (File I/O) في C++

تعد عمليات الإدخال والإخراج للملفات (File I/O) أحد المواضيع الأساسية في البرمجة بلغة C++، حيث تُستخدم هذه العمليات لإجراء التفاعل بين البرنامج ونظام الملفات. يُعد التفاعل مع الملفات أداة حيوية للتخزين الدائم للبيانات، مما يتيح للبرامج حفظ البيانات واسترجاعها بعد إغلاق البرنامج. في هذا المقال، سنتناول بالتفصيل كيفية التعامل مع الملفات في C++ من خلال استخدام العمليات الأساسية للقراءة والكتابة، إضافة إلى تقنيات أخرى متقدمة تسهم في تحسين الأداء وتجعل البرمجة أكثر مرونة وكفاءة.

تعريف عمليات الدخول والخروج للملفات في C++

الدخول والخروج للملفات (File I/O) يشير إلى العمليات التي يقوم بها البرنامج لقراءة البيانات من الملفات أو كتابتها إلى الملفات. عند الحديث عن الملفات في هذا السياق، فإننا نعني جميع أنواع الملفات التي يحتوي عليها جهاز الكمبيوتر، مثل النصوص، ملفات البيانات، الصور، الملفات الثنائية، وغيرها.

الملفات يمكن أن تكون من نوعين رئيسيين:

  1. الملفات النصية (Text Files): هي الملفات التي تحتوي على نصوص يمكن قراءتها بواسطة البشر وتخزين البيانات بشكل نصي.

  2. الملفات الثنائية (Binary Files): هي الملفات التي تحتوي على بيانات في شكل ثنائي، مما يجعلها غير قابلة للقراءة المباشرة من قبل البشر ولكنها أكثر كفاءة في تخزين البيانات المعقدة.

في لغة C++، يتم التعامل مع ملفات الإدخال والإخراج باستخدام دوال الإدخال والإخراج (I/O functions) والتي توفرها مكتبات C++ القياسية مثل .

المكتبات المستخدمة في التعامل مع الملفات

في C++، يتم استخدام المكتبات التالية للتعامل مع الملفات:

  1. : هذه المكتبة توفر فئات التعامل مع الملفات في C++. تحتوي على ثلاث فئات رئيسية:

    • ifstream: لقراءة البيانات من الملفات (Input File Stream).

    • ofstream: لكتابة البيانات إلى الملفات (Output File Stream).

    • fstream: التي توفر إمكانية القراءة والكتابة على نفس الملف (File Stream).

إليك مثالًا بسيطًا باستخدام هذه المكتبة:

cpp
#include #include int main() { std::ofstream outFile("example.txt"); // فتح ملف للكتابة if (outFile.is_open()) { outFile << "Hello, world!" << std::endl; // كتابة نص إلى الملف outFile.close(); // غلق الملف } std::ifstream inFile("example.txt"); // فتح ملف للقراءة std::string line; if (inFile.is_open()) { while (getline(inFile, line)) { // قراءة كل سطر من الملف std::cout << line << std::endl; } inFile.close(); // غلق الملف } return 0; }

فتح الملفات بأنماط مختلفة

عند فتح الملفات في C++، يمكن تحديد أنماط الفتح، وهي ما تحدد الطريقة التي سيتم بها التعامل مع الملف. هذه الأنماط يتم تمريرها كوسائط إلى الكائنات من النوع ifstream أو ofstream أو fstream.

الأنماط الرئيسية للفتح في C++:

  • ios::in: فتح الملف للقراءة.

  • ios::out: فتح الملف للكتابة.

  • ios::app: فتح الملف في وضع الإضافة (append)، مما يعني أن الكتابة ستكون دائمًا في نهاية الملف.

  • ios::trunc: إذا كان الملف موجودًا مسبقًا، فسيتم مسحه (حذفه) قبل الكتابة عليه.

  • ios::binary: فتح الملف في وضع ثنائي (مناسب للملفات الثنائية).

  • ios::ate: فتح الملف في نهاية الملف، مما يعني أنه سيبدأ الكتابة أو القراءة من نهاية الملف.

  • ios::app: فتح الملف في وضع الإضافة.

إليك مثالًا على فتح ملف باستخدام أنماط مختلفة:

cpp
#include #include int main() { // فتح الملف في وضع الكتابة والإضافة std::ofstream outFile("example.txt", std::ios::app); if (outFile.is_open()) { outFile << "Appending text!" << std::endl; outFile.close(); } return 0; }

القراءة من الملفات النصية

قراءة البيانات من الملفات النصية في C++ تُعتبر عملية أساسية، ويمكن القيام بها باستخدام الكائن ifstream (مدخلات الملف). يعتمد البرنامج في هذه الحالة على دوال مثل getline() لقراءة الأسطر أو استخدام عامل القراءة >> لقراءة البيانات بشكل منفصل.

استخدام getline():

cpp
#include #include int main() { std::ifstream inFile("example.txt"); std::string line; if (inFile.is_open()) { while (getline(inFile, line)) { std::cout << line << std::endl; } inFile.close(); } return 0; }

في هذا المثال، يتم قراءة كل سطر من الملف إلى متغير line باستخدام الدالة getline() التي تقرأ السطر بأكمله بما في ذلك المسافات.

استخدام >> لقراءة البيانات:

cpp
#include #include int main() { std::ifstream inFile("example.txt"); std::string word; if (inFile.is_open()) { while (inFile >> word) { std::cout << word << std::endl; } inFile.close(); } return 0; }

هنا، يتم قراءة الكلمات من الملف واحدة تلو الأخرى باستخدام >>، حيث يتوقف عند كل فاصل (مثل المسافة أو السطر الجديد).

الكتابة إلى الملفات النصية

كتابة البيانات إلى الملفات النصية تتم باستخدام الكائن ofstream (مخرجات الملف). يمكن استخدام دوال الكتابة مثل << أو write() لكتابة النصوص والبيانات.

الكتابة باستخدام <<:

cpp
#include #include int main() { std::ofstream outFile("example.txt"); if (outFile.is_open()) { outFile << "Hello, file!" << std::endl; outFile.close(); } return 0; }

في هذا المثال، يتم كتابة النص إلى الملف باستخدام <<. إذا كان الملف موجودًا مسبقًا، فسيتم مسحه وكتابة النص الجديد.

الكتابة باستخدام write():

cpp
#include #include int main() { std::ofstream outFile("example.txt", std::ios::binary); if (outFile.is_open()) { const char* text = "Binary write example!"; outFile.write(text, strlen(text)); outFile.close(); } return 0; }

يتم في هذا المثال الكتابة إلى الملف بشكل ثنائي باستخدام write(). هنا يتم تحديد الحجم الفعلي للبيانات باستخدام دالة strlen() التي تعطي طول السلسلة النصية.

التعامل مع الملفات الثنائية

الملفات الثنائية في C++ تُستخدم لتخزين البيانات في شكل غير قابل للقراءة بواسطة البشر. يتم التعامل معها باستخدام fstream في وضع ثنائي (binary mode).

مثال على قراءة وكتابة ملفات ثنائية:

cpp
#include #include int main() { // كتابة بيانات إلى ملف ثنائي std::ofstream outFile("example.bin", std::ios::binary); if (outFile.is_open()) { int data = 12345; outFile.write(reinterpret_cast<char*>(&data), sizeof(data)); outFile.close(); } // قراءة بيانات من ملف ثنائي std::ifstream inFile("example.bin", std::ios::binary); int dataRead; if (inFile.is_open()) { inFile.read(reinterpret_cast<char*>(&dataRead), sizeof(dataRead)); std::cout << "Data read: " << dataRead << std::endl; inFile.close(); } return 0; }

في هذا المثال، يتم تخزين عدد صحيح (int) في ملف بتنسيق ثنائي باستخدام write()، ثم قراءته باستخدام read().

التعامل مع الأخطاء في عمليات الإدخال والإخراج للملفات

من المهم التعامل مع الأخطاء أثناء عمليات الإدخال والإخراج للملفات، مثل محاولة فتح ملف غير موجود أو فشل الكتابة في ملف. توفر C++ عدة طرق للتحقق من وجود الأخطاء، مثل استخدام الدالة is_open() أو fail().

cpp
#include #include int main() { std::ofstream outFile("example.txt"); if (!outFile) { std::cerr << "Error opening file for writing!" << std::endl; return 1; } outFile << "Hello, world!"; outFile.close(); std::ifstream inFile("nonexistentfile.txt"); if (inFile.fail()) { std::cerr << "Error opening file for reading!" << std::endl; } return 0; }

التحقق من الأخطاء

  • is_open(): تتحقق من أن الملف قد تم فتحه بنجاح.

  • fail(): تتحقق إذا كانت عملية القراءة أو الكتابة قد فشلت.