قراءة ملف (Reading a File)
سنقوم الآن بإضافة وظيفة لقراءة الملف المحدد في وسيط (argument) file_path. أولاً، نحتاج إلى ملف عينة لاختباره: سنستخدم ملفاً يحتوي على كمية صغيرة من النص عبر عدة أسطر مع بعض الكلمات المتكررة. تحتوي القائمة 12-3 على قصيدة لإميلي ديكنسون (Emily Dickinson) ستعمل بشكل جيد! أنشئ ملفاً يسمى poem.txt في المستوى الجذر لمشروعك، وأدخل قصيدة “I’m Nobody! Who are you?”.
I'm nobody! Who are you?
Are you nobody, too?
Then there's a pair of us - don't tell!
They'd banish us, you know.
How dreary to be somebody!
How public, like a frog
To tell your name the livelong day
To an admiring bog!
مع وجود النص في مكانه، قم بتحرير src/main.rs وأضف كوداً لقراءة الملف، كما هو موضح في القائمة 12-4.
use std::env;
use std::fs;
fn main() {
// --snip--
let args: Vec<String> = env::args().collect();
let query = &args[1];
let file_path = &args[2];
println!("Searching for {query}");
println!("In file {file_path}");
let contents = fs::read_to_string(file_path)
.expect("Should have been able to read the file");
println!("With text:\n{contents}");
}
أولاً، نقوم باستيراد جزء ذي صلة من المكتبة القياسية (standard library) باستخدام جملة use: نحتاج إلى std::fs للتعامل مع الملفات.
في main ، تأخذ الجملة الجديدة fs::read_to_string الـ file_path ، وتفتح ذلك الملف، وتُرجع قيمة من نوع std::io::Result<String> تحتوي على محتويات الملف.
بعد ذلك، نضيف مرة أخرى جملة println! مؤقتة تطبع قيمة contents بعد قراءة الملف حتى نتمكن من التحقق من أن البرنامج يعمل حتى الآن.
دعونا نشغل هذا الكود مع أي سلسلة نصية (string) كأول وسيط لواجهة الأوامر (لأننا لم ننفذ جزء البحث بعد) وملف poem.txt كوسيط ثانٍ:
$ cargo run -- the poem.txt
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep the poem.txt`
Searching for the
In file poem.txt
With text:
I'm nobody! Who are you?
Are you nobody, too?
Then there's a pair of us - don't tell!
They'd banish us, you know.
How dreary to be somebody!
How public, like a frog
To tell your name the livelong day
To an admiring bog!
رائع! قام الكود بقراءة محتويات الملف ثم طباعتها. لكن الكود به بعض العيوب. في الوقت الحالي، تمتلك دالة main مسؤوليات متعددة: بشكل عام، تكون الدوال أوضح وأسهل في الصيانة إذا كانت كل دالة مسؤولة عن فكرة واحدة فقط. المشكلة الأخرى هي أننا لا نعالج الأخطاء (handling errors) بشكل جيد كما يمكننا. لا يزال البرنامج صغيراً، لذا فإن هذه العيوب ليست مشكلة كبيرة، ولكن مع نمو البرنامج، سيكون من الصعب إصلاحها بشكل نظيف. من الممارسات الجيدة البدء في إعادة الهيكلة (refactoring) في وقت مبكر عند تطوير البرنامج لأنه من الأسهل بكثير إعادة هيكلة كميات أصغر من الكود. سنفعل ذلك بعد ذلك.