I have a ./file.txt
that is:
Lorem ipsum
dolor sit
amet
I want the same ./file.txt
to be:
dolor sit
amet
I don't care about the file in any other way; I'm not going to be doing any further manipulation on it or anything like that. I only want to strip the first line.
std::fs::write
overrides the entire content of a file. I asssume I would need to read the entire file into a String, remove everything from the start of the string until I find a new line (somehow), then override the entire file with that new string. Though maybe it's just me, all of that feels a bit overkill. I do not care for the entire contents of the file.
The reason I'm asking is because I simply do not know how to do this, especially so if there's a better way of going about this whole thing. If there is an obvious simple answer that'd be great.
This question was answered for Rust 1.0, which is rather outdated, to the point where BufReader.lines()
no longer exists.
Did more research, this is the closest I ended up getting.
I don't know if this is optimal, and am not entirely certain this preserves the formatting of the file (though I think it does). I think probably also, there's a better way of loading the file. I don't know many things.
But it works?
use std::{fs, fs::File, fs::OpenOptions};
use std::io::{BufReader, BufRead, Write};
fn main() {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open("./file.txt")
.expect("file.txt doesn't exist or so");
let mut lines = BufReader::new(file).lines().skip(1)
.map(|x| x.unwrap())
.collect::<Vec<String>>().join("\n");
fs::write("./file.txt", lines).expect("Can't write");
}
You have to read everything but the first line and then override the contents of the file. I'd do it like this:
use std::{
fs::File,
io::{self, prelude::*},
};
fn remove_first_line(path: &str) -> io::Result<()> {
let buf = {
let r = File::open(path)?;
let mut reader = io::BufReader::new(r);
reader.read_until(b'\n', &mut Vec::new())?;
let mut buf = Vec::new();
reader.read_to_end(&mut buf)?;
buf
};
File::create(path)?.write_all(&buf)?;
Ok(())
}
I create a BufReader
to read the first line, then I return whatever is left in the file and put it in once again.
If you don't want to close and open the file again, you have to change the seek position so you don't append data to the file:
use std::{
fs::OpenOptions,
io::{self, prelude::*},
};
fn remove_first_line(path: &str) -> io::Result<()> {
let file = OpenOptions::new().read(true).write(true).open(path)?;
let mut reader = io::BufReader::new(file);
reader.read_until(b'\n', &mut Vec::new())?;
let mut buf = Vec::new();
reader.read_to_end(&mut buf)?;
let mut file = reader.into_inner();
file.seek(io::SeekFrom::Start(0))?;
file.write_all(&buf)?;
Ok(())
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With