🚀 Buffered Streams في جافا: سر السرعة في قراءة وكتابة الملفات! ⚡
هل لاحظت أن قراءة ملف حرفاً بحرف أو كتابة بيانات صغيرة بشكل متكرر قد تكون بطيئة؟ 🐢 هذا لأن كل عملية قراءة أو كتابة تتطلب اتصالاً مباشراً مع نظام الملفات، وهي عملية "مكلفة" من حيث الوقت.
هنا تأتي Buffered Streams (التيارات المُخزّنة مؤقتاً) لتنقذ الموقف! 🦸♂️ فكر فيها كـ "وسيط ذكي" بين برنامجك وبين الملف. بدلاً من الذهاب للقراءة من القرص الصلب في كل مرة، تقوم بجمع كمية من البيانات (تخزنها في buffer) ثم تقدمها لك دفعة واحدة، مما يقلل عدد مرات الاتصال المباشر بالملف ويحسن الأداء بشكل كبير! ⏩
🧠 ما هو الـ Buffer (المخزن المؤقت)؟
الـ Buffer هو مجرد منطقة في الذاكرة (مصفوفة من البايتات أو الأحرف) تُستخدم لتخزين البيانات مؤقتاً قبل معالجتها.
- بدون Buffer: برنامجك ↔ نظام الملفات (بطيء).
- مع Buffer: برنامجك ↔ الذاكرة السريعة (Buffer) ↔ نظام الملفات (سريع جداً).
يتم ملء هذا المخزن المؤقت عند القراءة، وإفراغه عند الكتابة، مما يجعل العمليات أكثر كفاءة.
📦 فئات Buffered Streams في جافا
توفر جافا أربع فئات رئيسية في حزمة java.io لتعمل كـ "غلاف" (wrapper) حول الـ Streams العادية وتضيف لها خاصية التخزين المؤقت:
BufferedInputStream: تُغلفInputStream(مثلFileInputStream) لقراءة البايتات بشكل مُخزن مؤقت.BufferedOutputStream: تُغلفOutputStream(مثلFileOutputStream) لكتابة البايتات بشكل مُخزن مؤقت.BufferedReader: تُغلفReader(مثلFileReader) لقراءة الأحرف/النصوص بشكل مُخزن مؤقت. ⭐ (الأكثر استخداماً للقراءة).BufferedWriter: تُغلفWriter(مثلFileWriter) لكتابة الأحرف/النصوص بشكل مُخزن مؤقت. ⭐ (الأكثر استخداماً للكتابة).
✍️ مثال عملي: الكتابة باستخدام BufferedWriter
لنكتب عدة أسطر نصية إلى ملف باستخدام BufferedWriter، والذي سيجمعها في الذاكرة أولاً قبل كتابتها دفعة واحدة إلى الملف.
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class WriteWithBuffer {
public static void main(String[] args) {
// نستخدم try-with-resources للإغلاق التلقائي
try (FileWriter fw = new FileWriter("output.txt");
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write("Hello World from BufferedWriter!");
bw.newLine(); // كتابة سطر جديد (أفضل من استخدام \n)
bw.write("This is the second line.");
bw.newLine();
bw.write("Data is collected in memory first and then written.");
System.out.println("✅ Successfully written to the file using Buffer!");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
ملاحظة: لاحظ كيف أن BufferedWriter يغلف كائن FileWriter. ستجد الملف output.txt وقد كُتبت فيه الأسطر الثلاثة.
📖 مثال عملي: القراءة باستخدام BufferedReader
الآن لنقرأ محتويات ملف نصي سطراً سطراً. BufferedReader يوفر طريقة readLine() السهلة جداً لهذا الغرض.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadWithBuffer {
public static void main(String[] args) {
// نستخدم try-with-resources للإغلاق التلقائي
try (FileReader fr = new FileReader("output.txt");
BufferedReader br = new BufferedReader(fr)) {
String line;
System.out.println("📖 Contents of the file:");
// قراءة الملف سطراً سطراً حتى ينتهي (عندما تصبح القيمة null)
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output:
📖 Contents of the file:
Hello World from BufferedWriter!
This is the second line.
Data is collected in memory first and then written.
⚠️ نقطة مهمة: إفراغ الـ Buffer (Flushing)
عند الكتابة باستخدام BufferedOutputStream أو BufferedWriter، قد تبقى البيانات في الذاكرة (في الـ buffer) ولا تُكتب تلقائياً إلى الملف حتى يمتلئ الـ buffer.
- الطريقة
flush(): تجبر هذه الطريقة على كتابة جميع البيانات الموجودة في الـ buffer إلى الوجهة النهائية (الملف) فوراً، حتى لو لم يكن الـ buffer ممتلئاً. - الطريقة
close(): عند إغلاق الـ Stream، يتم استدعاءflush()تلقائياً أولاً لضمان كتابة كل البيانات المتبقية.
bw.write("بعض البيانات");
bw.flush(); // ➡️ نكتب البيانات إلى الملف الآن دون انتظار!
// ... عمليات أخرى
bw.close(); // سيؤدي flush() تلقائياً قبل الإغلاق
🆚 مقارنة سريعة: مع Buffer vs. بدون Buffer
| الميزة | بدون Buffer (مثل FileReader مباشرة) | مع Buffer (مثل BufferedReader) |
|---|---|---|
| السرعة | أبطأ، خاصة مع كميات كبيرة من البيانات | أسرع بكثير بسبب تقليل عمليات الإدخال/الإخراج |
| السهولة | قراءة حرف بحرف أو مصفوفة بايتات | يوفر طرقاً ملائمة مثل readLine() |
| كفاءة النظام | أقل كفاءة | أكثر كفاءة في استخدام موارد النظام |
🎯 الخلاصة
- Buffered Streams تضيف طبقة تخزين مؤقت (ذاكرة وسيطة) لتحسين أداء عمليات قراءة وكتابة الملفات.
- الفئات الأساسية هي:
BufferedReader,BufferedWriter,BufferedInputStream,BufferedOutputStream. - طريقة العمل: تقوم بتغليف (wrap) كائنات الـ Streams العادية.
- الأكثر استخداماً:
BufferedReader(معreadLine()) وBufferedWriterللتعامل مع النصوص. - تذكر دائماً إغلاق الـ Streams (باستخدام
try-with-resources) أو استخدامflush()عند الحاجة لضمان كتابة كل البيانات.
🎓 اختبر نفسك
التعليقات
شاركنا رأيك أو أسئلتك حول هذا المقال