파일 읽기

이제는 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: 에밀리 딕킨슨의 시는 좋은 테스트 케이스를 만들어 줍니다

텍스트를 채워 넣었다면 예제 12-4처럼 src/main.rs에 파일을 읽는 코드를 추가하세요.

파일명: 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!("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}");
}

예제 12-4: 두 번째 인수로 명시된 파일의 내용물 읽기

먼저 use 구문을 사용하여 표준 라이브러리의 연관된 부분을 가져옵니다: 파일을 다루기 위해서는 std::fs가 필요하죠.

main에서 새로운 구문 fs::read_to_stringfile_path를 받아서 그 파일을 열고, 파일 내용물의 std::io::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`
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 함수에는 여러 가지 기능이 있습니다: 일반적으로 함수 하나당 단 하나의 아이디어에 대한 기능을 구현할 때 함수가 더 명료해지고 관리하기 쉬워집니다. 또 한 가지 문제는 처리 가능한 수준의 에러 처리를 안 하고 있다는 점입니다. 프로그램은 아직 작고, 따라서 이러한 결점이 큰 문제는 아니지만, 프로그램이 커지면 이 문제들을 깔끔하게 고치기 어려워질 것입니다. 작은 양의 코드를 리팩터링하는 것이 훨씬 쉽기 때문에, 프로그램을 개발할 때 일찍 리팩터링하는 것은 좋은 관행입니다. 이걸 바로 다음에 하겠습니다.