developer tip

Rust 1.x에서 파일을 읽고 쓰는 사실상의 방법은 무엇입니까?

optionbox 2020. 8. 18. 07:39
반응형

Rust 1.x에서 파일을 읽고 쓰는 사실상의 방법은 무엇입니까?


Rust가 비교적 새롭기 때문에 파일을 읽고 쓰는 방법이 너무 많습니다. 많은 사람들이 블로그를 위해 만든 매우 지저분한 스 니펫이며, 내가 찾은 예제의 99 % (Stack Overflow에서도)는 더 이상 작동하지 않는 불안정한 빌드에서 나왔습니다. 이제 Rust가 안정 되었으니 파일을 읽거나 쓰기위한 간단하고 읽기 쉽고 당황하지 않는 스 니펫은 무엇입니까?

이것은 내가 텍스트 파일을 읽는 측면에서 작동하는 것에 가장 가깝지만 내가 가져야 할 모든 것을 포함했다고 확신하더라도 여전히 컴파일되지 않습니다. 이것은 모든 장소의 Google+에서 찾은 스 니펫을 기반으로하며 내가 변경 한 유일한 것은 이전 BufferedReader이 이제 다음과 같다는 것입니다 BufReader.

use std::fs::File;
use std::io::BufReader;
use std::path::Path;

fn main() {
    let path = Path::new("./textfile");
    let mut file = BufReader::new(File::open(&path));
    for line in file.lines() {
        println!("{}", line);
    }
}

컴파일러는 다음과 같이 불평합니다.

error: the trait bound `std::result::Result<std::fs::File, std::io::Error>: std::io::Read` is not satisfied [--explain E0277]
 --> src/main.rs:7:20
  |>
7 |>     let mut file = BufReader::new(File::open(&path));
  |>                    ^^^^^^^^^^^^^^
note: required by `std::io::BufReader::new`

error: no method named `lines` found for type `std::io::BufReader<std::result::Result<std::fs::File, std::io::Error>>` in the current scope
 --> src/main.rs:8:22
  |>
8 |>     for line in file.lines() {
  |>                      ^^^^^

요약하자면 제가 찾고있는 것은 다음과 같습니다.

  • 짧음
  • 가독성
  • 가능한 모든 오류를 다룹니다.
  • 당황하지 않는다

여기에 표시 한 기능 중 어느 것도 자체적으로 당황 expect하지 않지만 어떤 종류의 오류 처리가 귀하의 응용 프로그램에 가장 적합할지 모르기 때문에 사용 하고 있습니다. 자신의 프로그램에서 오류를 적절하게 처리하는 방법을 이해하려면 The Rust Programming Language오류 처리 장을 읽어보십시오 .

Rust 1.26 이상

기본 세부 사항에 관심이없는 경우 읽기 및 쓰기를위한 한 줄 함수가 있습니다.

파일 읽기 String

use std::fs;

fn main() {
    let data = fs::read_to_string("/etc/hosts").expect("Unable to read file");
    println!("{}", data);
}

파일을 Vec<u8>

use std::fs;

fn main() {
    let data = fs::read("/etc/hosts").expect("Unable to read file");
    println!("{}", data.len());
}

파일 쓰기

use std::fs;

fn main() {
    let data = "Some data!";
    fs::write("/tmp/foo", data).expect("Unable to write file");
}

Rust 1.0 이상

These forms are slightly more verbose than the one-line functions that allocate a String or Vec for you, but are more powerful in that you can reuse allocated data or append to an existing object.

Reading data

Reading a file requires two core pieces: File and Read.

Read a file to a String

use std::fs::File;
use std::io::Read;

fn main() {
    let mut data = String::new();
    let mut f = File::open("/etc/hosts").expect("Unable to open file");
    f.read_to_string(&mut data).expect("Unable to read string");
    println!("{}", data);
}

Read a file as a Vec<u8>

use std::fs::File;
use std::io::Read;

fn main() {
    let mut data = Vec::new();
    let mut f = File::open("/etc/hosts").expect("Unable to open file");
    f.read_to_end(&mut data).expect("Unable to read data");
    println!("{}", data.len());
}

Write a file

Writing a file is similar, except we use the Write trait and we always write out bytes. You can convert a String / &str to bytes with as_bytes:

use std::fs::File;
use std::io::Write;

fn main() {
    let data = "Some data!";
    let mut f = File::create("/tmp/foo").expect("Unable to create file");
    f.write_all(data.as_bytes()).expect("Unable to write data");
}

Buffered I/O

I felt a bit of a push from the community to use BufReader and BufWriter instead of reading straight from a file

A buffered reader (or writer) uses a buffer to reduce the number of I/O requests. For example, it's much more efficient to access the disk once to read 256 bytes instead of accessing the disk 256 times.

That being said, I don't believe a buffered reader/writer will be useful when reading the entire file. read_to_end seems to copy data in somewhat large chunks, so the transfer may already be naturally coalesced into fewer I/O requests.

Here's an example of using it for reading:

use std::fs::File;
use std::io::{BufReader, Read};

fn main() {
    let mut data = String::new();
    let f = File::open("/etc/hosts").expect("Unable to open file");
    let mut br = BufReader::new(f);
    br.read_to_string(&mut data).expect("Unable to read string");
    println!("{}", data);
}

And for writing:

use std::fs::File;
use std::io::{BufWriter, Write};

fn main() {
    let data = "Some data!";
    let f = File::create("/tmp/foo").expect("Unable to create file");
    let mut f = BufWriter::new(f);
    f.write_all(data.as_bytes()).expect("Unable to write data");
}

A BufReader is more useful when you want to read line-by-line:

use std::fs::File;
use std::io::{BufRead, BufReader};

fn main() {
    let f = File::open("/etc/hosts").expect("Unable to open file");
    let f = BufReader::new(f);

    for line in f.lines() {
        let line = line.expect("Unable to read line");
        println!("Line: {}", line);
    }
}

참고URL : https://stackoverflow.com/questions/31192956/whats-the-de-facto-way-of-reading-and-writing-files-in-rust-1-x

반응형