Read or write a whole file with FS, or keep a File open for several operations. Handle failures with Result and choose when the file closes with using or defer.
Install Topaz through First Program. The environment running your program must allow filesystem access. Importing a module does not grant that permission.
Read through one managed File
In a working folder, create a UTF-8 file named note.txt containing ready. Save this program beside it as files-resources.tpz.
function readNote(path: string) -> Result<string, string> {
let mut result: Result<string, string> = Err("not read")
using file = open(path)? {
result = file.read()
}
return result
}
match readNote("note.txt") {
case Ok(text) => print(text.trim())
case Err(error) => print(error)
}Run topaz run files-resources.tpz from that folder.
readyopen returns Ok(file) when the file opens. If opening fails, ? returns the error from readNote before entering the block.
After opening, using binds file and registers its close call. file.read() stores its Result in the outer variable. Leaving the block closes the file, then the function returns the stored result.
If note.txt is missing, the program prints the error from open. Restore the file in the working folder and run again. The Err branch prints an error string, so this program can exit successfully even when reading fails.
Choose FS or File
| Task | Call | Return type |
|---|---|---|
| Read all text | FS.readText(path) | Result<string, string> |
| Replace all text | FS.writeText(path, text) | Result<(), string> |
| Read all bytes | FS.readBytes(path) | Result<Bytes, string> |
| Replace all bytes | FS.writeBytes(path, bytes) | Result<(), string> |
| List a directory | FS.list(path) | Result<Array<{ kind: string, name: string, sizeBytes: Option<int> }>, string> |
| Keep a file open | open(path) | Result<File, string> |
FS accepts a Path or string. The write operations replace the file's contents. Choose a new path or keep a copy before overwriting data you need.
An open File uses these calls.
open(path: string) -> Result<File, string>
file.read() -> Result<string, string>
file.write(s: string) -> Result<(), string>
file.close() -> ()Use open to acquire the file and read or write for text. For whole-file binary data, use the FS byte operations. File.open, File.create, File.append, readLine, writeLine, and flush are unavailable.
Choose using or defer
| Where you need the file | Cleanup |
|---|---|
| Inside one block | using file = open(path)? { ... } closes it when the block exits |
| Across nested blocks in a function | Follow let file = open(path)? immediately with defer { file.close() } |
using creates an immutable binding in a child scope. Use the open file within that scope. Do not close it manually inside using, because the registered close still runs. Behavior after repeated closing can vary between runtimes.
Both forms clean up on normal exit and exits through return, postfix ?, break, or continue. A fault stops execution immediately. Cleanup after a fault is unspecified.
File access and supported operations
File,FS,std.fs, andstd.ioneed a profile that permits filesystem access. A profile defines which operations a program may use.- Module imports do not grant access to paths, environment variables, processes, networks, or databases.
- Opening, reading, and writing return failures as
Errvalues. Handle them withmatchor propagate them with?. Filehides its internal state and cannot be compared. Avoid using it after closing.File.writehas no portable append mode. Binary overloads, buffering, permission controls, and line-by-line methods are not specified forFile.usinghandles oneFile. User-defined cleanup protocols, multiple-resourceusing, asynchronous or cancellation cleanup, and cleanup at module exit are not supported.
Continue with Defer & Resources for cleanup order or Null, Option, Result & Faults for error propagation. Find other tasks in Standard Library Overview.