우선 프로젝트 루트,

그러니까 Cargo.toml이 있는 위치에 hello.txt를 만들어 보겠다.


use std::fs::File; // File 사용을 위해 필요 use std::io::prelude::*; // write_all 사용을 위해 필요 use std::path::Path; // Path 사용을 위해 필요 fn main() { // path: 프로젝트 루트(Cargo.toml 위치) + hello.txt let path: &Path = Path::new("hello.txt"); // 출력을 위한 Display 객체 let display: std::path::Display = path.display(); // create를 통해 파일을 쓰기 모드로 연다. let mut file: File = match File::create(&path) { Err(why) => panic!("couldn't create {}: {}", display, why), Ok(file) => file, }; // 파일에 쓸 내용 let hello = "Hello, Rust!"; // 파일에 쓰려면 as_bytes를 써야 한다. match file.write_all(hello.as_bytes()) { Err(why) => panic!("couldn't write to {}: {}", display, why), Ok(_) => println!("successfully wrote to {}", display), } }


결과:




프로젝트 루트에 있는 hello.txt




Hello, Rust!라 쓰여 있는 모습



보다시피 이미 파일이 존재해도 덮어 씌워 버릴 수 있다.


이제 파일을 읽는 것도 추가하여,

Hello, Rust!를 계속해서 다음 줄에 출력해 보겠다.


use std::fs::File; use std::io::prelude::*; // read_to_string을 위해 필요 use std::path::Path; fn main() { let path = Path::new("hello.txt"); let display = path.display(); // 파일을 우선 읽기 모드로 연다 let mut file = match File::open(&path) { Err(why) => panic!("couldn't open {}: {}", display, why), Ok(file) => file, }; // 파일을 스트링으로 변환한다. let mut s = String::new(); match file.read_to_string(&mut s) { Err(why) => panic!("couldn't read {}: {}", display, why), Ok(_) => println!("{} contains:\n{}", display, s), } // 스트링에 내용을 추가한다. s += "\nHello, Rust!"; // 이번엔 파일을 쓰기 모드로 연다. file = match File::create(&path) { Err(why) => panic!("couldn't create {}: {}", display, why), Ok(file) => file, }; // 파일에 내용을 작성한다. match file.write_all(s.as_bytes()) { Err(why) => panic!("couldn't write to {}: {}", display, why), Ok(_) => println!("successfully wrote to {}", display), } }


결과:




처음에 Hello, Rust!가 있었고,

두 번 실행하니 Hello, Rust!가 두 번 추가된 것을 확인할 수 있다.


또 파일을 한줄한줄씩 읽는 방법도 있다.

바로 lines라는 함수를 이용하는 것이다.


use std::fs::File; use std::io::{self, BufRead}; fn main() { // lines 함수를 이용해 만든 read_lines 함수를 호출한다. let file = File::open("hello.txt").unwrap(); // 여기 lines 함수가 핵심이다. let lines = io::BufReader::new(file).lines(); // lines를 이용해 반복문을 돌며 줄을 출력한다. for line in lines { if let Ok(ip) = line { // if let은 2편 컨트롤 플로우 편에서 설명한 적이 있다. println!("{}", ip); } } }


결과:



한줄한줄씩 출력해서 Hello, Rust!가 3번 나온 모습이다.


파일 입출력을 한다고 해도

초기 단계에선 이를 이용해 뭘 할 수 있을지 생각이 안 날 수가 있다.


왜냐하면 러스트 자체도 익숙하지가 않은데,

파일까지 건드려가면서 뭘 할 정신이 없을 수 있기 때문이다.


하지만 초기 단계에서부터 이를 활용할 수 있는 예시가 있는데,

바로 html, 정적 웹 페이지다.


다음 6편에서는 html 파일의 일부 내용을 이용하여

다른 html 내용으로 변경하는, 일명 파일 파싱에 대해서 알아보도록 하겠다.


이를 잘 이용하면 자신만의 정적 웹 페이지 생성기를 만들 수도 있다.

다만 그렇게 하려면 러스트랑 별개로 html, css, js 등에 대해서 알아야 되기는 한다.


웹 어셈블리, wasm에 대해서 알고 있는 사람도 있을 텐데,

그건 애플리케이션을 웹에 담을 때 유용한 것이지,

html의 내용 자체를 직접 건드리는 건 아직까지 js가 더 낫다.


코드: https://github.com/cmasfo/cmasfo