当前位置: 首页 > 知识库问答 >
问题:

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

花博厚
2023-03-14

由于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个答案

贺景胜
2023-03-14

通过使用缓冲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);
    }
}
储国发
2023-03-14

对于任何正在写入文件的人来说,接受的答案都很好,但如果需要附加到文件,则必须使用OpenOptions结构:

use std::io::Write;
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");
}
韩彦君
2023-03-14

我在这里展示的函数没有一个会自己产生恐慌,但我使用的是expect,因为我不知道哪种错误处理最适合您的应用程序。阅读Rust编程语言关于错误处理的章节,了解如何正确处理自己程序中的故障。

如果你不想关心底层细节,读写都有单行功能。

use std::fs;

fn main() {
    let data = fs::read_to_string("/etc/hosts").expect("Unable to read file");
    println!("{}", data);
}
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");
}

这些表单比为您分配字符串或Vec的单行函数稍微详细一些,但功能更强大,因为您可以重用分配的数据或附加到现有对象。

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

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

写入文件与此类似,只是我们使用写入特性,并且总是写出字节。您可以转换字符串

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和BufWriter,而不是直接从文件中读取

缓冲读取器(或写入器)使用缓冲区来减少I/O请求的数量。例如,一次访问磁盘读取256个字节要比访问磁盘256次有效得多。

也就是说,我不相信缓冲读写器在读取整个文件时会有用read\u to\u end似乎将数据复制成一些较大的块,因此传输可能已经自然地合并到更少的I/O请求中。

下面是一个用它来阅读的例子:

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更有用:

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);
    }
}
 类似资料:
  • 本文向大家介绍java读取文件和写入文件的方式(简单实例),包括了java读取文件和写入文件的方式(简单实例)的使用技巧和注意事项,需要的朋友参考一下 Java代码 Java代码 以上就是小编为大家带来的java读取文件和写入文件的方式(简单实例)全部内容了,希望大家多多支持呐喊教程~

  • null 如果我的理解有误,请指正。还有以下问题: 我的理解是,Hadoop中的文件读/写没有任何并行性,它所能执行的最佳操作与传统的文件读或写(即,如果复制设置为1)+分布式通信机制中涉及的一些开销是一样的。 并行性仅在数据处理阶段通过Map Reduce提供,而不是在客户端读/写文件期间提供。

  • 问题内容: 我必须阅读tomcat日志文件,并在一段时间(例如:一个小时)后再次读取该文件(仅针对新添加的内容),因此我创建了RandomAccessFile来记录我完成的最后一个位置并使用BufferedReader.readLine()方法。 但是,我发现有时我无法读取文件的整行。 例如,tomcat正在尝试编写以下内容(仅作为示例): 192.168.0.0本地主机/index.html .

  • 问题内容: 请看下面的代码 我正在尝试读取CSV文件,在代码中编辑文本,然后将其写回到.txt文件中。我的问题是,我有葡萄牙语单词,因此应使用ANSI格式读写文件。现在,输出文件中的某些葡萄牙语单词已替换为符号。 如何在Java中以ANSI格式读取文本数据并将其写入文件? 问题答案: 要读取具有特定编码的文本文件,可以将FileInputStream结合使用InputStreamReader。Wi

  • 问题内容: 我试图逐行读取文件,然后使用Node.js将其输出到另一个文件。 我的问题是由于Node.js的异步特性,行的顺序有时会混乱。 例如,我的输入文件就像:第1行第2行第3行 但是输出文件可能像:第1行第3行第2行 下面是我的代码。 任何想法将不胜感激,谢谢。 问题答案: 如果要编写同步代码,请仅使用同步功能: 对于异步方法,您可以编写类似

  • 本文向大家介绍c++读取和写入TXT文件的整理方法,包括了c++读取和写入TXT文件的整理方法的使用技巧和注意事项,需要的朋友参考一下 如下所示: 以上这篇c++读取和写入TXT文件的整理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。