لماذا العمل مع الملفات في Rust ليس ألماً، بل متعة؟
\n\nإذا كنت معتاداً على Python، حيث open() يحل كل شيء تقريباً، قد يبدو Rust كمعلم صارم. لكن خلف هذه الصرامة تكمن قوة لا تصدق. Rust لن يسمح لك بترك ملف مفتوحاً عن طريق الخطأ، أو قراءة البايتات كسلسلة نصية، أو نسيان التحقق من وجود دليل. في هذه المقالة، سنشرح العمل مع الملفات ونظام الملفات في Rust - من العمليات البسيطة إلى التقنيات المتقدمة. ستتعلم كيفية القراءة، الكتابة، الإنشاء، والحذف للملفات، وكذلك كيفية إدارة المسارات بفعالية.
هل أنت مستعد؟ هيا بنا!
\n\nالأساسيات: فتح، قراءة، إغلاق
\n\nفي Rust لا توجد دالة مدمجة open() كما في Python. بدلاً من ذلك، نستخدم الوحدة القوية std::fs. لنبدأ بأبسط شيء - قراءة ملف كامل.
قراءة ملف كامل إلى سلسلة نصية
\n\nأبسط طريقة لقراءة ملف هي استخدام std::fs::read_to_string. هذا مشابه لـ file.read() في Python، ولكن مع ضمان الأمان.
use std::fs;\n\nfn main() {\n let content = fs::read_to_string("hello.txt")\n .expect("لم يتمكن من قراءة الملف");\n println!("محتوى الملف:\\n{}", content);\n}\n\nلاحظ .expect(). في Rust لا توجد استثناءات - يوجد Result. إذا لم يكن الملف موجوداً، سيتعطل البرنامج مع رسالة مفهومة. للكود الإنتاجي، من الأفضل استخدام match أو unwrap_or_else، ولكن للتعلم، expect مثالي.
الكتابة في ملف
\n\nالكتابة بديهية أيضاً:
\n\nuse std::fs;\n\nfn main() {\n let data = "Hello, Rust!\\nهذه كتابة اختبارية.";\n fs::write("output.txt", data)\n .expect("لم يتمكن من كتابة الملف");\n println!("تم كتابة الملف بنجاح!");\n}\n\nالطريقة fs::write تنشئ الملف إذا لم يكن موجوداً، وتستبدل المحتوى إذا كان الملف موجوداً. لإضافة بيانات إلى نهاية الملف، استخدم OpenOptions.
العمل مع المسارات: Path و PathBuf
\n\nفي Rust هناك نوعان رئيسيان للعمل مع المسارات: Path (مستعار، غير قابل للتغيير) و PathBuf (خاص، قابل للتغيير). فهم الفرق بينهما هو مفتاح العمل الفعال مع نظام الملفات.
إنشاء ومعالجة المسارات
\n\nuse std::path::{Path, PathBuf};\n\nfn main() {\n // إنشاء مسار\n let path = Path::new("data/subdir/file.txt");\n \n // الحصول على مكونات المسار\n println!("الدليل الأب: {:?}", path.parent());\n println!("اسم الملف: {:?}", path.file_name());\n println!("الامتداد: {:?}", path.extension());\n \n // تجميع مسار جديد\n let mut new_path = PathBuf::from("backup");\n new_path.push("data");\n new_path.push("file.txt");\n println!("المسار الجديد: {}", new_path.display());\n}\n\nالطريقة .display() إلزامية إذا كنت تريد طباعة المسار في الطرفية. Rust لا يسمح بإدراج المسار مباشرة في سلسلة نصية - هذه حماية من مشاكل الترميز.
القراءة والكتابة: المستوى المتقدم
\n\nعندما تحتاج إلى تحكم أكبر، استخدم File و BufReader/BufWriter.
قراءة ملف سطراً سطراً
\n\nللملفات الكبيرة، قراءة كل شيء في الذاكرة غير فعالة. استخدم القراءة المخزنة:
\n\nuse std::fs::File;\nuse std::io::{BufRead, BufReader};\n\nfn main() {\n let file = File::open("large_file.txt")\n .expect("الملف غير موجود");\n let reader = BufReader::new(file);\n \n for (index, line) in reader.lines().enumerate() {\n let line = line.expect("خطأ في قراءة السطر");\n println!("السطر {}: {}", index + 1, line);\n }\n}\n\nهذا الأسلوب يسمح بمعالجة الملفات من أي حجم، دون تحميلها بالكامل في الذاكرة العاملة.
\n\nإضافة بيانات إلى نهاية الملف
\n\n