Scripting · File streams
File streams.
Use open(path) for convenient whole-file text, file(path) for managed transactional editing, and ifstream/ofstream when data should be consumed or produced incrementally.
Construct a stream with a path, or default-construct it and call .open(path) later. Close explicitly with .close() (or the compatible close(stream)); reopening after close is allowed, while opening an already-open stream is a fatal lifecycle error.
ifs := ifstream("data.txt") // open immediately
s := ""
n := 0
ifs >> s >> n // whitespace-token extraction
ifs.close() ifs := ifstream() // default construction
ifs.open("data.txt") // open later
s := ""
n := 0
ifs >> s >> n
ifs.close() ofs := ofstream("report.txt") // open immediately
ofs << "hello" << " " << 42 // chained insertion
ofs.write_line("done")
ofs.close() ofs := ofstream() // default construction
ofs.open("report.txt") // open later
ofs << "hello" << " " << 42
ofs.close() Input streams
stream := ifstream("data.txt")
line := stream.read_line()
rest := stream.read_all()
stream.close() | Method | Result |
|---|---|
read(n) | Read up to n bytes from the current position. |
read_line() | Read the next line. |
read_all() | Read the remaining stream contents. |
read_bytes(n) | Read up to n bytes as a bytes value. |
read_all_bytes() | Read the remaining stream as a bytes value. |
read_val() | Parse the next serialized Nift data value using Nift's value parser. |
eof() | Report the stream's EOF state. |
>> destination | Extract one whitespace-delimited token into a mutable scalar binding (string, number or boolean). |
open(path) | Open (or reopen) the stream. |
close() | Close the stream. |
EOF is a normal stream state, not an error: read_line() returns null at EOF and eof() becomes true. A >> extraction at EOF leaves the destination unchanged. A conversion failure while extracting into a typed destination is a fatal data error, not stream.read_failed.
values := ifstream("values.txt")
flag := values.read_val()
count := values.read_val()
items := values.read_val() read_val() reads exactly one value from the current stream position, skipping leading whitespace, and leaves the position immediately after that value (trailing whitespace is not consumed). It understands supported serialized Nift data values: null, true/false, integers, floating-point numbers, quoted strings, JSON arrays and JSON objects, including nested structures. At end of stream it returns null. Malformed input is a hard error — read_val() reports cannot parse value rather than silently becoming a string. It is only valid on input streams.
Output streams
out := ofstream("result.txt")
out.write("hello")
out.write_line(" world")
out.write_val({"count": 3, "ok": true})
out.write_bytes(bytes([65, 66, 67]))
out.flush()
out.close() ofstream(path) creates/truncates its output file. Streams are resource values with identity and closed-state checks; they are not directly renderable as template/console values.
write(value) writes a renderable scalar (strings and numbers) without quotes; write_line(value) appends a newline; write_bytes(bytes) writes raw bytes; << value is the chaining operator and writes through the same machinery as write(). To serialize structured data use write_val(value), which writes any value — scalar, array or object — as compact JSON followed by a newline. A write_val()/read_val() pair round-trips values through a file:
out := ofstream("data.jsonl")
out.write_val({"name": "nift", "tags": ["build", "static"]})
out.write_val([1, 2, 3])
out.close()
in := ifstream("data.jsonl")
first := in.read_val()
second := in.read_val()
print(first.name)
@// nift
print(first.tags[0])
@// build
print(second.size())
@// 3
in.close() Recoverable stream errors
A genuine backend failure on a valid stream operation is recoverable: stream.open_failed, stream.read_failed, stream.write_failed, stream.flush_failed and stream.close_failed (a delayed write surfaced at explicit close). These can be caught:
try {
s := ifstream("missing.txt")
} catch(err) {
print(err.code) // stream.open_failed
} Misuse stays fatal and bypasses catch: wrong direction (reading an output stream), operating on an unopened or closed stream, opening an already-open stream, invalid/forged handles, and non-renderable writes (including Error values). EOF and extraction conversion failures are also not stream.read_failed.