I wrote a bot that performs some network queries once every so often and dumps the latest state into a file stored on disk. This is my code:
let log_file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&log_file_name)
.unwrap();
serde_json::to_writer(
log_file,
&State {
foo: self.foo,
bar: self.bar
},
)
.unwrap();
The issue is that, occasionally, the size of the newest state json will be smaller than the size of the previous state JSON. This leaves that portion of the previous state JSON that is longer than the new state JSON to remain in the log file:
{"foo": 1,"bar": 2}"baz": 3}
In the example above, "baz": 3}
is the leftover data from the previous state JSON.
The question is: how can I rewrite the code so that I first flush all the contents of the file and then write the new state json?
I know deleting the file is a solution but I would prefer not to do that.
You additionally need the truncate
flag, which results in the file being truncated to length 0 if it already exists. Additionally, you should remove the read
flag, since you are not actually reading from the log file.
Since write
, create
, truncate
is a very common combination of flags, there is a shortcut: You don't need to use the more low-level OpenOptions
interface, and can instead use File::create()
:
let log_file = File::create(&log_file_name).unwrap();
The implementation of File::create()
simply spells out the long version using OpenOptions
:
pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())
}
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