什么是在Rust 1.x中读取和写入文件的事实上的方法?

时间:2015-07-02 19:23:47

标签: file-io rust

由于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() {
  |>                      ^^^^^

总结一下,我正在寻找的是:

  • 简洁
  • 可读性
  • 涵盖所有可能的错误
  • 不会恐慌

3 个答案:

答案 0 :(得分:123)

我在这里展示的所有功能都没有自己恐慌,但我使用的是//n:field[@name='a'],因为我不知道哪种错误处理最适合您的应用程序。阅读 The Rust Programming Language chapter on error handling,了解如何正确处理自己程序中的失败。

Rust 1.26及以后

如果您不想关注底层细节,可以使用单行函数进行读写。

将文件读取到expect

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());
}

Rust 1.0及以后

这些表单比为您分配use std::fs; fn main() { let data = "Some data!"; fs::write("/tmp/foo", data).expect("Unable to write file"); } String的单行函数稍微冗长一些,但功能更强大,因为您可以重用已分配的数据或附加到现有对象。

读取数据

阅读文件需要两个核心部分:FileRead

将文件读取到Vec

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

Vec<u8>

写一个文件

写一个文件是类似的,除了我们使用Write特征,我们总是写出字节。您可以使用as_bytesuse 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()); } / String转换为字节:

&str

缓冲I / O

  

我觉得社区有点推动使用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"); } BufReader而不是直接从文件中阅读

缓冲读取器(或写入器)使用缓冲区来减少I / O请求的数量。例如,访问磁盘一次读取256个字节而不是访问磁盘256次效率更高。

话虽这么说,我不相信缓冲读写器在阅读整个文件时会有用。 read_to_end似乎以稍微大块的方式复制数据,因此传输可能已经自然地合并为更少的I / O请求。

以下是使用它进行阅读的示例:

BufWriter

写作:

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

当您想要逐行阅读时,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"); } 更有用:

BufReader

答案 1 :(得分:2)

对于正在写入文件的任何人,公认的答案是好的,但如果您需要附加到文件,则必须改用 OpenOptions 结构:

use std::fs::OpenOptions;

fn main() {
    let data = "Some data!\n";
    let mut f = OpenOptions::new()
        .append(true)
        .create(true) // Optionally create the file if it doesn't already exist
        .open("/tmp/foo")
        .expect("Unable to open file");
    f.write_all(data.as_bytes()).expect("Unable to write data");
}

缓冲写入仍然以相同的方式工作:

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

fn main() {
    let data = "Some data!\n";
    let f = OpenOptions::new()
        .append(true)
        .open("/tmp/foo")
        .expect("Unable to open file");
    let mut f = BufWriter::new(f);
    f.write_all(data.as_bytes()).expect("Unable to write data");
}

答案 2 :(得分:2)

通过使用 Buffered I/O 可以复制的文件大小大于实际内存。


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

fn main() {
    let read = File::open(r#"E:\1.xls"#);

    let write = OpenOptions::new().write(true).create(true).open(r#"E:\2.xls"#);

    let mut reader = BufReader::new(read.unwrap());

    let mut writer = BufWriter::new(write.unwrap());

    let mut length = 1;

    while length > 0 {
        let buffer = reader.fill_buf().unwrap();

        writer.write(buffer);

        length = buffer.len();
        reader.consume(length);
    }
}