قراءة وكتابة الملفات برمجياً باستخدام وحدة fs


سنتعلم اليوم كيفية قراءة وكتابة الملفات برمجياً باستخدام وحدة fs المدمجة في Node.js، مما يفتح لنا آفاقاً واسعة للتعامل مع البيانات المحلية.

مقدمة إلى وحدة fs في Node.js

وحدة fs (File System) هي وحدة أساسية في Node.js تتيح لنا التفاعل مع نظام الملفات على جهاز الحاسوب. يمكننا من خلالها إنشاء، قراءة، كتابة، تحديث، وحذف الملفات والمجلدات. تأتي هذه الوحدة بنسخ متزامنة (Synchronous) وغير متزامنة (Asynchronous) لكل عملية، وسنركز في هذا الدرس على النسخ المتزامنة لسهولة الفهم المبدئي.
ملاحظة تقنية: على الرغم من سهولة استخدام العمليات المتزامنة، إلا أنها تحظر سلسلة التعليمات الرئيسية (main thread) حتى تكتمل العملية، مما قد يؤثر على أداء التطبيقات الكبيرة. يفضل في بيئات الإنتاج استخدام العمليات غير المتزامنة (Callbacks, Promises, Async/Await) للحفاظ على استجابة التطبيق.

الخطوة 1: كتابة البيانات إلى ملف (fs.writeFileSync)

لإنشاء ملف جديد وكتابة محتوى فيه، أو استبدال محتوى ملف موجود، نستخدم الدالة fs.writeFileSync(). تستقبل هذه الدالة مسار الملف والمحتوى المراد كتابته.
// استيراد وحدة fs (File System)
const fs = require('fs');

const filePath = 'example.txt';
const fileContent = 'مرحباً بكم في درس قراءة وكتابة الملفات!\nهذا هو السطر الأول.';

try {
  // كتابة المحتوى إلى الملف بشكل متزامن
  // إذا كان الملف غير موجود، سيتم إنشاؤه.
  // إذا كان الملف موجوداً، سيتم استبدال محتواه بالكامل.
  fs.writeFileSync(filePath, fileContent, 'utf8');
  console.log('تم كتابة المحتوى إلى الملف بنجاح.');
} catch (error) {
  console.error('حدث خطأ أثناء الكتابة إلى الملف:', error);
}

الخطوة 2: قراءة البيانات من ملف (fs.readFileSync)

لقراءة محتوى ملف موجود، نستخدم الدالة fs.readFileSync(). تستقبل هذه الدالة مسار الملف وتعيد المحتوى كسلسلة نصية (string) إذا تم تحديد ترميز (encoding).
// استيراد وحدة fs (File System)
const fs = require('fs');

const filePath = 'example.txt';

try {
  // قراءة المحتوى من الملف بشكل متزامن
  // 'utf8' هو الترميز المستخدم لفك تشفير البيانات الثنائية إلى نص.
  const data = fs.readFileSync(filePath, 'utf8');
  console.log('\nتم قراءة المحتوى من الملف:');
  console.log(data);
} catch (error) {
  console.error('حدث خطأ أثناء قراءة الملف:', error);
}

الخطوة 3: إضافة بيانات إلى ملف موجود (fs.appendFileSync)

لإضافة محتوى جديد إلى نهاية ملف موجود دون مسح المحتوى القديم، نستخدم الدالة fs.appendFileSync(). هذه الدالة مفيدة لتسجيل السجلات (logs) أو إضافة بيانات تدريجياً.
// استيراد وحدة fs (File System)
const fs = require('fs');

const filePath = 'example.txt';
const additionalContent = '\nهذا سطر جديد تمت إضافته.';

try {
  // إضافة المحتوى إلى نهاية الملف بشكل متزامن
  fs.appendFileSync(filePath, additionalContent, 'utf8');
  console.log('\nتم إضافة المحتوى إلى الملف بنجاح.');
  
  // إعادة قراءة الملف للتأكد من الإضافة
  const updatedData = fs.readFileSync(filePath, 'utf8');
  console.log('محتوى الملف بعد الإضافة:');
  console.log(updatedData);
} catch (error) {
  console.error('حدث خطأ أثناء الإضافة إلى الملف:', error);
}

الخطوة 4: حذف ملف (fs.unlinkSync)

لحذف ملف من نظام الملفات، نستخدم الدالة fs.unlinkSync(). يجب توخي الحذر عند استخدام هذه الدالة لأنها تحذف الملف بشكل دائم.
// استيراد وحدة fs (File System)
const fs = require('fs');

const filePath = 'example.txt';

try {
  // التحقق مما إذا كان الملف موجوداً قبل محاولة حذفه
  if (fs.existsSync(filePath)) {
    // حذف الملف بشكل متزامن
    fs.unlinkSync(filePath);
    console.log('\nتم حذف الملف بنجاح.');
  } else {
    console.log('\nالملف غير موجود ليتم حذفه.');
  }
} catch (error) {
  console.error('حدث خطأ أثناء حذف الملف:', error);
}

الكود النهائي الكامل

إليكم الكود كاملاً لجميع العمليات التي تعلمناها في هذا الدرس، يمكنكم نسخه وتشغيله مباشرة باستخدام Node.js.
const fs = require('fs');

const filePath = 'example.txt';

console.log('--- بدء عمليات الملفات ---');

// 1. كتابة إلى ملف
try {
  const initialContent = 'مرحباً بكم في درس قراءة وكتابة الملفات!\nهذا هو السطر الأول.';
  fs.writeFileSync(filePath, initialContent, 'utf8');
  console.log('1. تم كتابة المحتوى الأولي إلى الملف بنجاح.');
} catch (error) {
  console.error('1. حدث خطأ أثناء الكتابة الأولية:', error);
}

// 2. قراءة من ملف
try {
  const data = fs.readFileSync(filePath, 'utf8');
  console.log('\n2. محتوى الملف بعد الكتابة:');
  console.log(data);
} catch (error) {
  console.error('2. حدث خطأ أثناء قراءة الملف:', error);
}

// 3. إضافة إلى ملف
try {
  const additionalContent = '\nهذا سطر جديد تمت إضافته الآن.';
  fs.appendFileSync(filePath, additionalContent, 'utf8');
  console.log('\n3. تم إضافة المحتوى الجديد إلى الملف بنجاح.');
  
  const updatedData = fs.readFileSync(filePath, 'utf8');
  console.log('   محتوى الملف بعد الإضافة:');
  console.log(updatedData);
} catch (error) {
  console.error('3. حدث خطأ أثناء الإضافة إلى الملف:', error);
}

// 4. حذف ملف
try {
  if (fs.existsSync(filePath)) {
    fs.unlinkSync(filePath);
    console.log('\n4. تم حذف الملف بنجاح.');
  } else {
    console.log('\n4. الملف غير موجود ليتم حذفه.');
  }
} catch (error) {
  console.error('4. حدث خطأ أثناء حذف الملف:', error);
}

console.log('\n--- انتهاء عمليات الملفات ---');

النتيجة المتوقعة

عند تشغيل السكربت أعلاه باستخدام Node.js (مثال: node your_script_name.js)، ستشاهد المخرجات التالية في الطرفية، كما سيتم إنشاء ملف باسم example.txt، ثم تحديثه، وأخيراً حذفه.
--- بدء عمليات الملفات ---
1. تم كتابة المحتوى الأولي إلى الملف بنجاح.

2. محتوى الملف بعد الكتابة:
مرحباً بكم في درس قراءة وكتابة الملفات!
هذا هو السطر الأول.

3. تم إضافة المحتوى الجديد إلى الملف بنجاح.
   محتوى الملف بعد الإضافة:
مرحباً بكم في درس قراءة وكتابة الملفات!
هذا هو السطر الأول.
هذا سطر جديد تمت إضافته الآن.

4. تم حذف الملف بنجاح.

--- انتهاء عمليات الملفات ---