io – How can I prepend a line to the beginning of a file? – Code Utility

I’m trying to add a new line to the beginning of a text file. I start by opening the file with append but that only allows me to use write_all to write to the end of the file, at least that’s the result I’m getting. If I read the documentation correctly, this is by design.

I’ve tried to play with seek, but that didn’t solve it.

This is what I have currently:

let mut file = OpenOptions::new().append(true).open(&file_path).unwrap();;
file.write_all(b"Cool days\n");

If I open the file with write, I end up overriding data instead of adding. What would be the appropriate way to go about accomplishing this with Rust?


You can’t do this directly in any programming language. See some other questions on the same topic in C#, Python, NodeJs, PHP, Bash and C.

There are several solutions with different trade-offs:

  1. Copy the entire file into memory, write the data you want, and then write the rest of the file after it. If the file is large, this might be a bad solution because of the amount of memory it will use, but might be suitable for small files, because it is simple to implement.

  2. Use a buffer, the same size as the text you want to prepend. Copy chunks of the file at a time into memory and then overwrite it with the previous chunk. In this way, you can shuffle the contents of the file along, with the new text at the start. This is likely to be slower than the other approaches, but will not require a large memory allocation. It could also be the best choice when the process doesn’t have permission to delete the file. But be careful: If the process is interrupted, this approach could leave the file in a corrupted state.

  3. Write the new data to a temporary file and then append the contents of the original. Then delete the original and rename the temporary file. This is a good solution because it delegates the heavy lifting to the operating system, and the original data is backed up so will not be corrupted if the process is interrupted.

From searching on Stack Overflow, the third solution seems to be the most popular answer for other languages, e.g. in Bash. This is likely to be because it is fast, safe and can often be implemented in just a few lines of code.

A quick Rust version looks something like this:

extern crate mktemp;
use mktemp::Temp;
use std::{fs, io, io::Write, fs::File, path::Path};

fn prepend_file<P: AsRef<Path>>(data: &u8, file_path: &P) -> io::Result<()> {
    // Create a temporary file 
    let mut tmp_path = Temp::new_file()?;
    // Stop the temp file being automatically deleted when the variable
    // is dropped, by releasing it.
    // Open temp file for writing
    let mut tmp = File::create(&tmp_path)?;
    // Open source file for reading
    let mut src = File::open(&file_path)?;
    // Write the data to prepend
    // Copy the rest of the source file
    io::copy(&mut src, &mut tmp)?;
    fs::rename(&tmp_path, &file_path)?;


fn main() -> io::Result<()> {
    let file_path = Path::new("file.txt");
    let data = "Data to add to the beginning of the file\n";
    prepend_file(data.as_bytes(), &file_path)?;


An example with 4 steps: (Peter’s solution #1)

  • create a vec holding data to preprend
  • open file, read content and append to vec
  • create file with same path, this will truncate (see doc File::create)
  • write content
use std::fs::File;
use std::path::Path;
use std::io::{Read, Write, Result};

fn prepend_file<P: AsRef<Path> + ?Sized>(data: &u8, path: &P) -> Result<()> {
    let mut f =  File::open(path)?;
    let mut content = data.to_owned();
    f.read_to_end(&mut content)?;

    let mut f = File::create(path)?;


fn main() -> Result<()> {
    prepend_file("hello world\n".as_bytes(), "/tmp/file.txt")

Peter’s solution works perfect, but it brings an extra crate, when dealing with small files, it’s good to avoid it.

Leave a Comment