파일 읽기
이제 file_path 인수로 지정된 파일을 읽는 기능을 추가해 봅시다. 먼저 이를 테스트할
샘플 파일이 필요합니다. 여러 줄에 걸친 짧은 텍스트이며, 반복되는 단어가 조금 있는
파일이면 좋습니다. 목록 12-3의 Emily Dickinson 시는 좋은 테스트 데이터가 됩니다!
프로젝트 루트에 poem.txt 라는 파일을 만들고, “I’m Nobody! Who are you?” 시를
넣어 보세요.
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! 문을 다시
추가합니다. 지금까지 프로그램이 잘 동작하는지 확인하기 위해서입니다.
아직 검색 기능을 구현하지 않았으므로 첫 번째 명령줄 인수에는 아무 문자열이나 넣고, 두 번째 인수에는 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 함수는 여러 책임을 동시에 지고 있습니다. 일반적으로 함수는
하나의 개념만 책임질 때 더 명확하고 유지보수하기 쉽습니다. 또 다른 문제는, 우리가
에러를 처리할 수 있는 방식보다 훨씬 덜 잘 처리하고 있다는 점입니다. 프로그램이 아직
작기 때문에 지금은 큰 문제처럼 보이지 않지만, 프로그램이 커질수록 이런 문제를
깔끔하게 고치기 어려워집니다. 프로그램을 개발할 때는 초기에 리팩터링을 시작하는 것이
좋습니다. 적은 양의 코드를 리팩터링하는 편이 훨씬 쉽기 때문입니다. 다음으로 그 작업을
해 보겠습니다.