首页 > 解决方案 > 写入文件时,OpenOptions write 无法正常工作

问题描述

所以我通过在 rust 中制作一个简单的 cat/bat 克隆来学习 rust,而且我似乎无法覆盖文件。

代码

use std::{fs::*, io::{Read, Write}};

fn main() {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .open("foo.txt")
        .unwrap();
    
    let mut contents = String::new();
    let mut formatted = String::new();

    file.read_to_string(&mut contents).unwrap();

    let mut i = 0;
    let mut formatted_line:String;

    for line in contents.split("\n") {
        formatted_line = format!("{}| {}",i,line);
        formatted.push_str(&formatted_line);
        i += 1;
    }

    file.write_all(formatted.as_bytes()).unwrap();
}

foo.txt 之前:

test
foo
bar

foo.txt 之后:

test
foo
bar0| test
1| foo
2| bar

根据我所阅读的内容以及以下文档中的内容fs.rs:747-748

/// If the file already exists, any write calls on it will overwrite its
/// contents, without truncating it.

.write(true)选项指定覆盖文件内容,并且该.append(true)选项附加到现有内容。但是从我编写的代码来看,程序忽略了写入 OpenOption,并附加到文件内容。我还尝试.append(false)了 OpenOptions 和相同的输出。

我使用的是 Windows 10 Home,而 foo.txt 是一个没有任何特殊权限或限制的 txt 文件。

Rust / Cargo 版本:
rustc 1.55.0 (c8dfcfe04 2021-09-06)
cargo 1.55.0 (32da73ab1 2021-08-23)

标签: filerust

解决方案


也许你最好使用简单的 fs::*,我知道,OpenOptions 如果你将创建多进程/线程代码,这个函数将面临竞争,所以可能(据我了解:读取所有然后删除所有并写入):

use std::fs::{File, write};
use std::io::Result;

fn main() -> Result<()>{
let mut file = File::open("foo.txt")?;
//Read(create copy if you need something simultaneous read before)
// file.try_clone()?;//simply, both files changes 
file.read_to_end(&mut your_string_or_vec)?;
//..... Your code
//and then truncate all
file_copy.set_len(0)?;
write("foo.txt", formatted.as_bytes())?;
}

另一种获取临时文件的方法(一个位置不重要(std::env::temp_dir()))

use std::fs::{File, write};
use tempfile::NamedTempFile;
use std::io:: Result;

fn main() -> Result<()>{
let mut read_from_file = String::new();
let mut formatted = String::new();

read_from_file = fs::read_to_string("foo.txt")?.parse()?;
for line in read_from_file.split("\n") {
        formatted_line = format!("{}| {}",i,line);
        formatted.push_str(&formatted_line);
        i += 1;
    }

let mut file_tmp1 = NamedTempFile::new()?;
println!("Let's write into temporary {:?}", file.path());

let mut file_tmp2 = file_tmp1.reopen()?;
writeln!(file_tmp1, formatted)?;

let mut buf = String::new();
file_tmp2.read_to_string(&mut buf)?;

fs::write("foo.txt",buf.as_bytes())?;
file_tmp1.close()?;
file_tmp2.close()?;

推荐阅读