Files: Writing
● Intermediate3 min
fs.write_text replaces a file in one step; fs.append_text adds to its end.
use std.fs
fn main() ! Error {
try fs.write_text("visits.log", "Asha\n")
try fs.append_text("visits.log", "Omar\n")
try fs.append_text("visits.log", "Zoe\n")
print(try fs.read_text("visits.log"))
try fs.write_text("visits.log", "reset\n")
print(try fs.read_text("visits.log"))
}The program ran and printed:
kavach run append.kav
AshaOmarZoe reset
append_textcreates the file if needed, then adds to its end: good for logs.write_textreplaces the whole file, atomically: a crash leaves the old text or the new, never half.fs.write_durablealso waits until the data is on the disk, so even a power cut keeps it. Databases build on it.
Piece by piece
fs.create_writer(path) gives a FileWriter, which writes a file as its data comes. A large upload or an export is never held in memory whole:
use std.fs
fn main() ! Error {
const w = try fs.create_writer("export.csv")
try w.write_text("id,total\n")
for id in [1, 2, 3] {
try w.write_text("{id},{id * 10}\n")
}
print(try w.finish())
print(try fs.read_text("export.csv"))
w.write_text("late") catch e => print(e)
}The program ran and printed:
kavach run writer.kav
24id,total1,102,203,30 Failed(path: "export.csv", reason: "finished")
| Function or method | Gives |
|---|---|
fs.create_writer(path) -> FileWriter ! FsError | A new, empty file at path to write; one already there is emptied |
w.write(data) ! FsError | Adds the Bytes data at the file's end. Writes are gathered in memory and go to the file 64 KB at a time |
w.write_text(text) ! FsError | The same for text, as UTF-8 |
w.finish(sync: false) -> Int ! FsError | Writes what is gathered, closes the file, and gives how many bytes it holds. With sync: true it also forces them to the disk (fsync), so a rename after it can't leave a short file after a crash |
- After
finish,writefails withFailed(path, "finished"), as the last line shows, andfinishgives the same count again. - It needs
Fs.write, and withuses Fs("…")the path must be inside its folders, as for every file operation.
A writer let go before finish closes its file and deletes it, so an upload cut short leaves nothing behind:
use std.fs
fn upload(path: String) ! FsError uses Fs {
const w = try fs.create_writer(path)
try w.write_text("the first half")
// returns before finish: the writer is let go
}
fn main() ! Error {
try upload("photo.jpg")
print(fs.exists("photo.jpg"))
}The program ran and printed:
kavach run writer-dropped.kav
falseUnlike write_text, the file is written in place, not replaced at once: other programs can see it grow. When that matters, write to another name and rename it, as the spec's example does:
fn save(pieces: [Bytes], path: String) -> Int ! FsError uses Fs.write {
const w = try fs.create_writer("{path}.part")
for piece in pieces {
try w.write(piece)
}
const size = try w.finish(sync: true)
try fs.rename("{path}.part", path)
size
}