مقدمه

در درس قبل، یاد گرفتیم که چگونه آرگومان‌های ورودی را از خط فرمان بخوانیم. حالا که مسیر فایل مورد نظر را از کاربر دریافت کرده‌ایم، مرحله بعدی خواندن محتوای آن فایل است. کتابخانه استاندارد Rust یک ماژول بسیار غنی به نام std::fs برای کار با‌ فایل‌سیستم (filesystem) فراهم می‌کند. در این درس، از تابع fs::read_to_string برای خواندن کل محتوای یک فایل در یک String استفاده خواهیم کرد.

خواندن محتوای فایل با fs::read_to_string

تابع read_to_string یک مسیر فایل را به عنوان آرگومان دریافت کرده و یک Result<String, std::io::Error> برمی‌گرداند. این یعنی عملیات ممکن است با موفقیت انجام شده و یک String حاوی محتوای فایل را برگرداند، یا با یک خطای I/O (ورودی/خروجی) مواجه شده و یک Err را برگرداند.

بیایید کد برنامه minigrep خود را برای خواندن فایل به‌روزرسانی کنیم. ابتدا، برای تست، یک فایل به نام poem.txt در ریشه پروژه خود با محتوای زیر ایجاد کنید:

Copy Icon poem.txt
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 را برای خواندن این فایل تغییر می‌دهیم:

Copy Icon src/main.rs
use std::{env, fs};

fn main() {
    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);
}

در این کد، ما ابتدا ماژول fs را وارد کرده‌ایم. سپس، با استفاده از fs::read_to_string و پاس دادن مسیر فایل، محتوای آن را می‌خوانیم. از آنجایی که این تابع یک Result برمی‌گرداند، ما از متد expect برای مدیریت خطا استفاده کرده‌ایم. اگر خواندن فایل با موفقیت انجام شود، expect محتوای فایل (یک String) را برمی‌گرداند. اگر با خطا مواجه شود، برنامه با پیامی که ما مشخص کرده‌ایم، panic خواهد کرد.

حالا می‌توانید برنامه را با cargo run -- a poem.txt (با فرض اینکه a کلمه‌ای است که در شعر وجود ندارد) اجرا کنید و خروجی کامل فایل را در ترمینال مشاهده کنید.

بهبود کد با بازسازی (Refactoring)

کد فعلی ما کار می‌کند، اما تمام منطق آن در تابع main قرار دارد. با رشد برنامه، این کار مدیریت کد را سخت می‌کند. بیایید کد را با انتقال منطق به توابع و structهای جداگانه، بازسازی کنیم. این کار نه تنها کد را سازماندهی می‌کند، بلکه به ما اجازه می‌دهد تا منطق را به صورت جداگانه تست کرده و خطاها را به شکل بهتری مدیریت کنیم.

در درس‌های بعدی این فصل، ما این پروژه را قدم به قدم بازسازی خواهیم کرد تا به یک ساختار قوی و قابل نگهداری برسیم.

در این درس، ما با استفاده از std::fs::read_to_string توانستیم محتوای یک فایل را در برنامه خود بخوانیم. این یک قدم بزرگ در ساخت ابزار خط فرمان ماست. با این حال، کد ما هنوز شکننده است و منطق آن متمرکز شده. در درس بعدی، «بهبود ماژولاریتی و مدیریت خطا»، با جداسازی مسئولیت‌ها و استفاده از Result به جای panic، کد خود را به یک سطح حرفه‌ای‌تر ارتقا خواهیم داد.