Nanfeng

Notes on software development, code, and curious ideas

Input and Output in Lua

Lua’s I/O library has a simple model based on current input/output files and a complete model based on explicit file handles. Explicit handles are clearer for all but tiny scripts.

Reading a file

1
2
3
4
5
6
7
local file, err = io.open("notes.txt", "r")
if not file then error(err) end

for line in file:lines() do
print(line)
end
file:close()

file:read("l") reads a line without its newline, "L" keeps the newline in supported versions, "a" reads the remainder, and "n" reads a number. Avoid reading an unbounded file all at once when its size is not trusted.

io.lines(filename) returns an iterator and automatically closes the file at end-of-file:

1
2
3
for line in io.lines("notes.txt") do
print(line)
end

Writing safely

1
2
3
4
local output, err = io.open("result.txt", "w")
assert(output, err)
assert(output:write("answer=", 42, "\n"))
assert(output:close())

Modes include r, w, and a, optionally combined with + and binary b. Opening with w truncates an existing file. For important data, write to a temporary file in the same directory, flush and close it, then replace the destination using an operating-system-appropriate atomic operation.

Standard streams and positioning

io.stdin, io.stdout, and io.stderr are standard handles. file:seek("set", offset), "cur", and "end" reposition seekable files. Text-mode offsets may not behave like raw byte offsets on every platform.

Always handle open, read, write, and close failures. Lua’s garbage collector may eventually close an abandoned file, but deterministic closure avoids descriptor exhaustion and ensures buffered output is reported promptly.

+