强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Lua 从入门到精通 / 13 - 文件与 I/O / File & System I/O

文件与 I/O / File & System I/O

Lua 的 I/O 库提供两种模式:简单模式(使用隐式文件句柄)和完全模式(使用显式文件句柄)。生产环境推荐完全模式。

Lua’s I/O library offers two modes: simple (implicit handle) and complete (explicit handle). Production code should use the complete mode.


🟢 基础 / Basics

1. 读写文件 / Reading & Writing Files

-- 写文件
local file = io.open("test.txt", "w")
file:write("Hello, Lua!\n")
file:write("Line 2\n")
file:close()

-- 读取整个文件
local file = io.open("test.txt", "r")
local content = file:read("*a")    -- *a = 全部内容
file:close()
print(content)

-- 逐行读取
local file = io.open("test.txt", "r")
for line in file:lines() do
    print(line)
end
file:close()

2. 文件模式 / File Modes

-- "r"  只读(默认)/ read
-- "w"  只写(覆盖)/ write (truncate)
-- "a"  追加 / append
-- "r+" 读写 / read + write
-- "w+" 读写(覆盖)/ read + write (truncate)
-- "a+" 读写(追加)/ read + write (append)
-- "rb" 二进制读 / binary read
-- "wb" 二进制写 / binary write

3. read() 的格式 / read() Formats

local file = io.open("data.txt", "r")

file:read("*n")    -- 读取一个数字
file:read("*a")    -- 读取整个文件
file:read("*l")    -- 读取一行(默认,不含换行符)
file:read("*L")    -- 读取一行(含换行符)
file:read(10)      -- 读取 10 个字节

-- 读取多个值
local name, age = file:read("*l", "*n")

4. 标准 I/O / Standard I/O

-- io.input / io.output 设置默认输入/输出文件
io.input("input.txt")
io.output("output.txt")

-- 简单模式(使用隐式文件句柄)
io.write("Hello!\n")
local line = io.read("*l")

-- io.write vs print
io.write("a", "b", "c")    -- abc(无空格无换行)
print("a", "b", "c")       -- a	b	c(有 tab 和换行)

🟡 进阶 / Intermediate

1. 安全的文件操作 / Safe File Operations

-- 模式一:pcall 包裹
local function safeRead(path)
    local file, err = io.open(path, "r")
    if not file then return nil, err end
    local content = file:read("*a")
    file:close()
    return content
end

local content, err = safeRead("missing.txt")
if not content then print("Error: " .. err) end

-- 模式二:确保文件关闭(类似 try-finally)
local function withFile(path, mode, fn)
    local file, err = io.open(path, mode)
    if not file then return nil, err end
    local ok, result = pcall(fn, file)
    file:close()
    if not ok then error(result) end
    return result
end

withFile("data.txt", "r", function(f)
    for line in f:lines() do
        print(line)
    end
end)

2. 临时文件 / Temporary Files

-- 创建临时文件
local tmpname = os.tmpname()
print(tmpname)    -- /tmp/lua_XXXXXX

local f = io.open(tmpname, "w")
f:write("temporary data")
f:close()

-- 使用完后删除
os.remove(tmpname)

-- io.tmpfile() 创建自动清理的临时文件
local tmp = io.tmpfile()
tmp:write("auto-cleaned")
tmp:seek("set", 0)
print(tmp:read("*a"))
tmp:close()    -- 关闭时自动删除

3. 文件定位 / File Positioning

local f = io.open("test.txt", "r+")

-- seek(whence, offset)
-- whence: "set" (文件开头), "cur" (当前位置), "end" (文件末尾)

f:seek("set", 0)      -- 回到文件开头
f:seek("end", -10)    -- 从末尾倒数 10 字节
f:seek("cur", 5)      -- 从当前位置前进 5 字节

local pos = f:seek()  -- 获取当前位置
print(pos)

f:close()

4. 目录操作 / Directory Operations

-- Lua 没有内置的目录操作,但可以用 os.execute 或 lfs 库

-- 列出文件(Linux/macOS)
local function listFiles(dir)
    local files = {}
    local pipe = io.popen('ls -1 "' .. dir .. '"')
    for file in pipe:lines() do
        files[#files + 1] = file
    end
    pipe:close()
    return files
end

-- os.execute 执行系统命令
os.execute("mkdir -p /tmp/lua_test")
os.execute("rm -f /tmp/lua_test/file.txt")

-- io.popen 执行命令并捕获输出
local pipe = io.popen("uname -a")
local sysinfo = pipe:read("*a")
pipe:close()
print(sysinfo)

-- LuaFileSystem (lfs) 库
-- local lfs = require("lfs")
-- lfs.chdir("/tmp")
-- lfs.mkdir("newdir")
-- for entry in lfs.dir(".") do print(entry) end

🔴 高级 / Advanced

1. 流式处理大文件 / Streaming Large Files

-- 逐行处理,不会一次性加载到内存
local function processLargeFile(path)
    local file = assert(io.open(path, "r"))
    local lineNum = 0
    for line in file:lines() do
        lineNum = lineNum + 1
        -- 处理每一行
        if lineNum % 10000 == 0 then
            io.stderr:write("Processed " .. lineNum .. " lines\n")
        end
    end
    file:close()
    return lineNum
end

-- 分块读取二进制文件
local function readFileChunks(path, chunkSize)
    chunkSize = chunkSize or 4096
    local file = assert(io.open(path, "rb"))
    return function()
        local chunk = file:read(chunkSize)
        if not chunk then file:close() end
        return chunk
    end
end

for chunk in readFileChunks("large.bin", 8192) do
    -- 处理每个 chunk
end

2. os 库常用函数 / os Library Functions

os.time()                    -- 当前时间戳
os.date("*t")                -- 当前日期时间表
os.date("%Y-%m-%d %H:%M:%S") -- 格式化日期
os.difftime(t2, t1)          -- 两个时间戳的差(秒)
os.execute("command")        -- 执行系统命令(返回状态码)
os.exit(0)                   -- 退出程序
os.getenv("PATH")            -- 获取环境变量
os.remove("file.txt")        -- 删除文件
os.rename("old", "new")      -- 重命名
os.tmpname()                 -- 生成临时文件名
os.clock()                   -- CPU 时间(精度高于 os.time)

-- 实用:计时器
local start = os.clock()
-- ... 要计时的代码 ...
local elapsed = os.clock() - start
print(string.format("Time: %.3f seconds", elapsed))

小结 / Summary

层级你需要知道的 / What You Need to Know
🟢 基础io.open/close/read/write/lines、文件模式、标准 I/O
🟡 进阶pcall 安全操作、临时文件、seek 定位、os.execute、io.popen
🔴 高级流式大文件处理、分块读取、os 库全貌、LuaFileSystem

下一章:垃圾回收 / Garbage Collection