How to put variable in file.write_all() function

I want to put variable in file.write_all() function. in the documentation they don't show how to do that, so how to do that?
Here's is the code

use std::io;
use std::io::prelude::*;
use std::process;
use std::fs::File;


fn main() {

  loop {
    println!("View People or add a new Person? (view/add/quit)");

    // asking user if they want to view people or add a new person
    let mut view_or_add: String = String::new();
    io::stdin()
    .read_line(&mut view_or_add)
    .expect("Something went wrong");
    let view_or_add: String = view_or_add.trim().to_lowercase();

    match view_or_add.as_str() {
      "view" => view_people(),
      "add" => add_person(),
      "quit" => process::exit(0),
      _ => {
        println!("Invalid command");
        continue;
      },
    };
  };

}


fn add_person() {
  // person name
  println!("Person name >>");
  let mut person_name: String = String::new();
  io::stdin()
  .read_line(&mut person_name)
  .expect("Something went wrong");
  let name: &str = person_name.trim();

  // person age
  let age: u32 = loop {
    println!("Person age >>");
    let mut person_age: String = String::new();
    io::stdin()
    .read_line(&mut person_age)
    .expect("Something went wrong");
    let person_age: u32 = match person_age.trim().parse() {
      Ok(num) => num,
      Err(_) => {
        println!("It's not a valid age!");
        continue;
      },
    };

    break person_age;
  };

  // person hobby
  println!("Person hobby >>");
  let mut person_hobby: String = String::new();
  io::stdin()
  .read_line(&mut person_hobby)
  .expect("Something went wrong");
  let hobby: &str = person_hobby.trim();
  
  let person_data = format!("name: {}, age: {}, hobby: {}", name, age, hobby);

  let mut file = File::create("people_list.txt").expect("Oops Something Went Wrong");
  file.write_all(b"{}", person_data);
  println!("Successfully added");
}


fn view_people() {
  // get people list from people_list.txt file
  let mut file = File::open("people_list.txt").expect("Oops Something Went Wrong");
  let mut contents = String::new();
  file.read_to_string(&mut contents);
  
  println!("The people list:");
  println!("{}", contents);
}

I assume you are asking how to fix this line:

let person_data = format!("name: {}, age: {}, hobby: {}", name, age, hobby);
file.write_all(b"{}", person_data);

The write_all method does not support any formatting options. The only thing you can pass to it is a byte slice. In this particular case, you would change it to the following:

let person_data = format!("name: {}, age: {}, hobby: {}", name, age, hobby);
file.write_all(person_data.as_bytes()).expect("Failed to write");

This uses the str::as_bytes method to get the string data as a byte slice.


An alternative to the above is to use the write! macro instead of format!. This avoids the need to create a temporary String to hold the data you are writing. For example:

write!(file, "name: {}, age: {}, hobby: {}", name, age, hobby).expect("Failed to write");

There's also a writeln! macro that will add a newline at the end of the data being written.


One disadvantage of the write! macro is that it performs many small writes, which can result in bad performance. The format! macro is one way to avoid that, since you only write to the file once. Another way is to wrap the File object in an BufWriter, which will "combine" all of your small writes into one larger write. However, if you do that, you have to be careful to remember to call flush on the BufWriter after writing to it.

1 Like

I still get problem though, when i add more than one person to the people.txt, new person overwritten the previous person i don't want that, i want when i add new person it added to people.txt not overwrite it

If you don't want the file to be overwritten, don't create it explicitly, but open with create-if-absent flag set via options.

Can you give me code examples?

Do you mean like this if yes it doesn't work

  
  let mut file = OpenOptions::new().append(true).open("foo.txt");
  file.write(b"some text").expect("Opps something went wrong");

You need to make sure it creates the file if it doesn't already exist.

let mut file = OpenOptions::new()
    .create(true)
    .append(true)
    .open("foo.txt");

Still error though
This this the full code

use std::fs::OpenOptions;

fn main() {
    let mut file = OpenOptions::new()
      .create(true)
      .append(true)
      .open("foo.txt");
  file.write(b"some text").expect("Opps something went wrong");
    
}

When you say it doesn't work, you should explain in what way. Does it not create the file? Is it still being overwritten? Does it print some error without creating the file? Does it fail to compile?

The error comes from write function it's says method not found

This is the error message

error[E0599]: no method named `write` found for enum `Result` in the current scope
 --> src/main.rs:8:8
  |
8 |   file.write(b"some text").expect("Opps something went wrong");
  |        ^^^^^ method not found in `Result<File, std::io::Error>`

Please read chapter 9 in the Rust book. You can find it here.

1 Like