Files and I/O
Prerequisites: Error handling
Writing and reading files
local f = assert(io.open("notes.txt", "w"))
f:write("first line\n", "second line\n")
f:close()
f = assert(io.open("notes.txt", "a"))
f:write("third line\n")
f:close()
f = assert(io.open("notes.txt", "r"))
local content = f:read("a")
f:close()
io.write(content)
print(#content)
first line
second line
third line
34
| Mode | Meaning |
|---|---|
"r" |
read (the default) |
"w" |
write — creates or truncates the file |
"a" |
append |
"rb", "wb" |
binary mode (matters on Windows) |
f:read formats: "a" whole file, "l" next line, "n" a number,
or a number of bytes.
Line by line
local f = assert(io.open("app.log", "w"))
f:write("INFO start\nERROR db timeout\nINFO request\nERROR disk full\n")
f:close()
local errors = 0
for line in io.lines("app.log") do
if line:find("^ERROR") then
errors = errors + 1
print(line:sub(7))
end
end
print(errors .. " errors")
db timeout
disk full
2 errors
io.lines(filename) opens the file, iterates over its lines, and closes
it at the end — the simplest way to process a file.
Closing automatically
Lua 5.4 adds to-be-closed variables — the file is closed when the variable goes out of scope, even if an error occurs:
local function firstLine(path)
local f <close> = assert(io.open(path))
return f:read("l")
end
local out = assert(io.open("data.txt", "w"))
out:write("hello\nworld\n")
out:close()
print(firstLine("data.txt"))
hello
Other file operations
local f = assert(io.open("old.txt", "w")); f:close()
print(os.rename("old.txt", "new.txt"))
local h = io.open("new.txt")
print(h ~= nil)
h:close()
print(os.remove("new.txt"))
print(os.remove("new.txt"))
true
true
true
nil new.txt: No such file or directory 2
Close files before renaming or deleting them — on Windows, an open file can't be removed.
Standard Lua has no function to list a directory — use the
LuaFileSystem library (lfs.dir), or the host's API (Neovim has
vim.fs, LÖVE has love.filesystem).