什么是在Rust 1.x中读写文件的事实上的方式? [英] What's the de-facto way of reading and writing files in Rust 1.x?

查看:188
本文介绍了什么是在Rust 1.x中读写文件的事实上的方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用Rust比较新,我看到了太多的读写文件的方法。许多人是非常杂乱的片段,有人提出他们的博客,我发现的例子(即使在堆栈溢出)的99%是来自不稳定的构建,不再工作。既然Rust是稳定的,那么读取或写入文件是一个简单的,可读的,非恐慌的片段?

这是最接近我的东西在阅读一个文本文件方面,但它仍然不编译,即使我相当肯定,我已经包括了我应该有的一切。这是基于我在Google+上发现的所有地方的一个片段,而我唯一改变的地方就是旧的 BufferedReader 现在只是 BufReader

 使用std :: fs :: File; 
使用std :: io :: BufReader;
使用std :: path :: Path;

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






编译器抱怨:

错误:特征绑定了`std :: result :: Result< std :: fs :: File,std :: io :: Error>:std :: io :: Read`不满足[--explain E0277]
- > src / main.rs:7:20
|>
7 |> let mut file = BufReader :: new(File :: open(& path));
|> ^^^^^^^^^^^^^^
注意:需要`std :: io :: BufReader :: new`

错误:没有名为`lines`的方法在当前作用域中找到类型为`std :: io :: BufReader< std :: result :: Result< std :: fs :: File,std :: io :: Error>>`
- > ; src / main.rs:8:22
|>
8 |> for line in file.lines(){
|>总结一下,我正在寻找的是:




>


  • 简洁

  • 可读性

  • >
  • 不会惊慌


解决方案

File 阅读字符串的所有内容:

 使用std :: fs :: File; 
使用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);



$ b $ p
$ b

如果你想把所有的东西都看成一组字节:

 使用std :: fs :: File; 
使用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(无法读取数据);
println!({},data.len());



$ b

没有一个函数自己是恐慌的,但是我使用 expect 因为我不知道什么样的错误处理最适合你的应用程序。
$ b

这些比为您分配 String Vec 的假设版本,但功能更强大,您可以重复使用分配的数据或追加到现有的对象。写一个为你分配对象的小包装是微不足道的,将来可能是一个符合人体工程学的添加。



写一个文件是一样的,字节。你可以用 / & str < -lang.org/std/string/struct.String.html#method.as_bytes-1rel =nofollow noreferrer> as_bytes

 使用std :: fs :: File; 
使用std :: io :: Write;

fn main(){
let data =有些数据!;
let mut f = File :: create(/ tmp / foo)。expect(Unable to create file);
f.write_all(data.as_bytes())。expect(无法写入数据);

$ / code $ / pre

lockquote

我觉得有点推社区使用 BufReader BufWriter 而不是直接从文件中读取


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



这就是说,我不相信缓冲区读取/写入器在读取整个文件时非常有用。 read_to_end 似乎将数据以较大的块复制,所以传输可能已经自然地合并为更少的IO请求。



下面是一个使用它的例子:

 使用std :: fs :: File; 
使用std :: io :: {Read,BufReader};

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

$ / code>

写作:

 使用std :: fs :: File; 
使用std :: io :: {Write,BufWriter};

fn main(){
let 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(无法写入数据);

$ / code>

BufReader 是当你想逐行阅读时更有用:

 使用std :: fs :: File; 
使用std :: io :: {BufRead,BufReader};
$ b $ f $ main(){
let f = File :: open(/ etc / hosts)。
let f = BufReader :: new(f);

在f.lines(){
中让line = line.expect(Unable to read line);
println!(Line:{},line);


code $
$ b $ hr

With Rust being comparatively new, I've seen far too many ways of reading and writing files. Many are extremely messy snippets someone came up with for their blog, and 99% of the examples I've found (even on Stack Overflow) are from unstable builds that no longer work. Now that Rust is stable, what is a simple, readable, non-panicking snippet for reading or writing files?

This is the closest I've gotten to something that works in terms of reading a text file, but it's still not compiling even though I'm fairly certain I've included everything I should have. This is based off of a snippet I found on Google+ of all places, and the only thing I've changed is that the old BufferedReader is now just 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);
    }
}

The compiler complains:

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

To sum it up, what I'm looking for is:

  • brevity
  • readability
  • covers all possible errors
  • doesn't panic

解决方案

You need two core pieces: File and Read.

If you want to read everything 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);
}

If you want to read everything as a set of bytes:

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

None of the functions panic on their own, but I am using expect because I don't know what kind of error handling would fit best into your application.

These are slightly more verbose than hypothetical versions that would allocate a String or Vec for you, but are more powerful in that you can reuse allocated data or append to an existing object. Writing a small wrapper that allocates the object for you is trivial, and might be an ergonomic addition in the future.

Writing a file is the same, except it's always done as 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");
}

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 IO 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 IO requests.

Here's an example of using it:

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

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::{Write, BufWriter};

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


这篇关于什么是在Rust 1.x中读写文件的事实上的方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆