ファイルを読み込む

では、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!

リスト12-3: エミリー・ディキンソンの詩は、いいテストケースになる

テキストを適当な場所に置いて、src/main.rsを編集し、ファイルを読むコードを追加してください。 リスト12-4に示したようにですね。

ファイル名: src/main.rs

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");

    //       "テキスト:\n{contents}"
    println!("With text:\n{contents}");
}

リスト12-4: 第2引数で指定されたファイルの中身を読み込む

最初に、use文で、標準ライブラリの関係のある箇所を持ってきています: ファイルを扱うのにはstd::fsが必要です。

mainに追加したfs::read_to_string文は、file_pathを受け取り、そのファイルを開き、 そのファイルの内容を含むstd::io::Result<String>を返します。

その後、今回もファイル読み込み後にcontentsの値を出力する一時的なprintln!文を追記しているので、 ここまでプログラムがきちんと動作していることを確認できます。

第1コマンドライン引数には適当な文字列(まだ検索する箇所は実装してませんからね)を、第2引数に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`
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関数は複数の責任を受け持っています: 一般に、各関数がただ一つの責任だけを持つようになれば、 関数は明確かつ、管理しやすくなります。もう一つの問題点は、できうる限りのエラー処理を怠っていることです。 まだプログラムが小規模なので、これらの欠陥は大きな問題にはなりませんが、プログラムが大規模になるにつれ、 それを綺麗に解消するのは困難になっていきます。プログラムを開発する際に早い段階でリファクタリングを行うのは、 良い戦術です。リファクタリングするコードの量が少なければ、はるかに簡単になりますからね。次は、それを行いましょう。