ファイルを読む
次に、file_path
引数で指定されたファイルを読む機能を追加します。まず、これをテストするためのサンプルファイルが必要です。複数行にわたる少量のテキストと、いくつかの繰り返し語を含むファイルを使います。リスト12-3
には、これにちょうどよい Emily Dickinson の詩があります! プロジェクトのルートレベルに
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に示されています。
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}");
}
まず、use
文を使って標準ライブラリの関連部分を取り込みます。ファイルを扱うには std::fs が必要です。
main では、新しい文 fs::read_to_string が file_path を受け取り、
そのファイルを開き、ファイルの内容を含む std::io::Result<String> 型の値を返します。
その後、ファイルが読まれたあとに contents の値を出力する一時的な println!
文を再び追加し、ここまでプログラムが正しく動いていることを確認できるようにします。
このコードを、最初のコマンドライン引数には任意の文字列を(まだ検索部分を実装していないため)、 2番目の引数には 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 関数は複数の責務を
持っています。一般に、各関数がただ1つの考えだけを担当しているほうが、関数はより明確で保守しやすくなります。もう1つの問題は、エラー処理が
できる限りうまく行われていないことです。プログラムはまだ小さいので、これらの
欠点は大きな問題ではありません。しかし、プログラムが大きくなるにつれて、それらをきれいに修正することは難しくなります。プログラムを開発するときは、早い段階でリファクタリングを始めるのがよい習慣です。というのも、少ない量のコードのほうがリファクタリングしやすいからです。次はそれを行います。