std.fs
API summary (generated from the Beans source by npm run coverage): 15 package functions.
std.fs gives you one-call helpers to read or write a whole file. Under the hood
it opens a File, does the work, and closes it.
Read the source at
stdlib/std/fs/fs.b.
Every function returns a Result, because
filesystem work can fail. Use ? to pass the error up.
import std.fsReading
Section titled “Reading”pub fn read_bytes(path: string) -> Result<Bytes>pub fn read(path: string) -> Result<string>read_bytesopens the file, reads it whole from offset 0, and returns the bytes.readdoes the same and fills its returned string directly. It does not build an intermediateBytesvalue.
Writing
Section titled “Writing”pub fn write_bytes(path: string, data: Bytes) -> Result<int>pub fn write(path: string, data: string) -> Result<int>pub fn append_bytes(path: string, data: Bytes) -> Result<int>pub fn append(path: string, data: string) -> Result<int>pub fn copy(from: string, to: string) -> Result<int>All five return the number of bytes written.
write_bytesandwriteopen the file in “create” mode, truncate it to empty, and write starting at position 0.writetakes a string;write_bytestakesBytes. Text writes use the string storage directly.append_bytesandappendopen the file in “append” mode and adddatato the end instead of truncating.copyuses the platform file-copy path when available and a fixed-size fallback. It does not hold the whole source file in a Beans buffer. A same-file or hard-link copy fails before the destination can be truncated.
import std.ioimport std.fs
fn main() { fs.write("greeting.txt", "hello\n").expect("write") fs.append("greeting.txt", "again\n").expect("append") let text: string = fs.read("greeting.txt").expect("read") io.print(text) // hello / again}Durability
Section titled “Durability”pub fn write_durable(path: string, data: string) -> Result<int>pub fn write_bytes_durable(path: string, data: Bytes) -> Result<int>pub fn sync(path: string) -> Result<bool>write_durable and write_bytes_durable truncate, write, flush and close on the
same handle, returning the byte count. Empty input still truncates and flushes.
They add one OS flush to an ordinary write and do not reopen the file.
sync opens an existing file in "rw" mode, flushes and closes it without
creating or truncating it. It requires read/write permission on every platform
for the portable Windows contract. It adds one open, one flush and one close.
The helpers propagate open, write, flush and successful-path close errors. Cleanup after an earlier error preserves that error. A failed write may leave the file changed; there is no rollback.
These calls request fsync on POSIX or FlushFileBuffers on Windows, subject to
filesystem and device guarantees. They flush file contents; directory entries
remain the responsibility of Dir.sync. Writes truncate in place.
For atomic replacement, write a distinct temporary file in the destination
directory using write_durable, rename it over the destination, then call
Dir.sync on the parent directory. Sync both directories for a move between
directories. Coordinate concurrent writers yourself. Directory sync on Windows
is currently best effort, so success does not prove metadata durability.
Directories stay on Dir: use create, create_all, list, walk, remove,
remove_all, exists, current, temp_path and sync directly.
Asking about a path
Section titled “Asking about a path”pub fn exists(path: string) -> boolpub fn size(path: string) -> Result<int>existsanswers yes or no and never fails: a path you cannot reach is a path that is not there, as far as this call is concerned.sizeis the file’s length in bytes without reading it.
Moving and removing
Section titled “Moving and removing”pub fn rename(from: string, to: string) -> Result<bool>pub fn remove(path: string) -> Result<bool>pub fn temp_dir() -> stringrenamemoves a file atomically within a filesystem, replacingtoif it is there. It can fail across filesystems and does not fall back to copying.removeanswersok(true)when it deleted the file andok(false)when there was nothing to delete. Only a real failure — a permission, a directory in the way — comes back aserr, so “make sure this is gone” needs noexistscheck first.temp_diris the directory the platform hands out for scratch files. It is a path, not a file: create your own name under it, and clean up after yourself.
import std.ioimport std.fsimport std.path
fn main() { let scratch: string = path.join(fs.temp_dir(), "notes.txt") fs.write(scratch, "draft\n").expect("write") io.println(fs.size(scratch).expect("size")) // 6 fs.remove(scratch).expect("remove") io.println(fs.exists(scratch)) // false}See also
Section titled “See also”- Files and mapping, the
Filetype for positional and cursor I/O when you need finer control. - std.path, build the path strings you pass here.
- std.reader, read a file line by line instead of all at once.