讀取檔案
現在我們要加上能夠讀取 file_path
中命令列引數指定的檔案功能。首先我們需要有個檔案範本能讓我們測試,我們可以建立一個文字檔,其中由數行重複的單字組成少量文字。範例 12-3 Emily Dickinson 的詩就是不錯的選擇!在專案根目錄建立一個檔案叫做 poem.txt,然後輸入此詩「I’m Nobody! Who are you?」
檔案名稱: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 來加上讀取檔案的程式碼,如範例 12-4 所示。
檔案名稱:src/main.rs
use std::env;
use std::fs;
fn main() {
// --省略--
let args: Vec<String> = env::args().collect();
let query = &args[1];
let file_path = &args[2];
println!("搜尋 {}", query);
println!("目標檔案為 {}", file_path);
let contents = fs::read_to_string(file_path)
.expect("應該要能夠讀取檔案");
println!("文字內容:\n{contents}");
}
首先,我們加上另一個 use
陳述式來將標準函式庫中的另一個相關部分引入:我們需要 std::fs
來處理檔案。
在 main
中,我們加上新的陳述式:fs::read_to_string
會接收 file_path
、開啟該檔案並回傳檔案內容的 Result<String>
。
在陳述式之後,我們再次加上暫時的 println!
陳述式來在讀取檔案之後,顯示 contents
的數值,讓我們能檢查程式目前運作無誤。
讓我們用任何字串作為第一個命令列引數(因為我們還沒實作搜尋的部分)並與 poem.txt 檔案作為第二個引數來執行此程式碼:
$ cargo run -- the poem.txt
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep the poem.txt`
搜尋 the
目標檔案為 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!
很好!程式碼有讀取並印出檔案內容。但此程式碼有些缺陷。main
函式負責太多事情了,通常如果每個函式都只負責一件事的話,函式才能清楚直白且易於維護。另一個問題是我們盡可能地處理錯誤。由於程式還很小,此缺陷不算什麼大問題,但隨著程式增長時,這會越來越難清楚地修正。在開發程式時盡早重構是很好的做法,因為重構少量的程式碼會比較簡單。接下來就讓我們開始吧。