文章目录

Lua 文件操作:io.open() 与 io.read()

发布于 2026-04-03 23:33:12 · 浏览 3 次 · 评论 0 条

Lua 文件操作:io.open() 与 io.read()

在 Lua 中读取或写入文件,核心靠两个函数:io.open() 打开文件,io.read() 从已打开的文件中读取内容。掌握它们的配合使用,就能完成绝大多数本地文件读取任务。


第一步:用 io.open() 打开文件

调用 io.open() 函数来打开一个文件。它需要两个参数:

  1. 文件路径(字符串)
  2. 打开模式(字符串)

常用模式包括:

  • "r":只读(默认),文件必须存在
  • "w":只写,会清空原文件内容
  • "a":追加写入
  • "rb" / "wb":以二进制模式读/写(跨平台更安全)

执行以下代码打开当前目录下的 data.txt 文件用于读取:

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

如果文件不存在或路径错误,io.open() 返回 nil 和一条错误信息。务必检查返回值是否有效:

local file, err = io.open("data.txt", "r")
if not file then
    print("打开失败:", err)
    return
end

第二步:用 io.read() 从文件读取内容

注意:io.read() 默认从标准输入(如键盘)读取。要让它从你刚打开的文件读取,必须先将文件设为当前输入流,或直接在文件对象上调用 read 方法。

方法一:设置全局输入流(不推荐)

io.input(file)  -- 将 file 设为默认输入
local content = io.read("*all")  -- 读全部内容

这种方式会影响后续所有 io.read() 调用,容易引发混乱。

方法二:直接在文件对象上调用 read()(推荐)

调用文件对象的 :read() 方法,这是最清晰、安全的做法:

local line = file:read("*line")   -- 读一行(不含换行符)
local all  = file:read("*all")    -- 读整个文件
local n    = file:read(10)        -- 读10个字符

常见读取模式说明:

模式参数 作用说明
"*all" 读取文件剩余全部内容,返回一个字符串
"*line" 读取下一行(到换行符为止),不包含换行符;文件末尾返回 nil
n(数字) 读取最多 n 个字符;若不足则读到文件末尾

示例:逐行读取文件

local file = io.open("log.txt", "r")
if not file then return end

while true do
    local line = file:read("*line")
    if not line then break end  -- 到达文件末尾
    print("读到一行:", line)
end

file:close()

第三步:关闭文件

调用 :close() 方法关闭文件,释放系统资源:

file:close()

即使脚本结束时 Lua 会自动关闭文件,也必须显式关闭——否则在长时间运行的程序中可能耗尽文件句柄。

更稳妥的做法是使用 “确保关闭”模式

local file, err = io.open("config.ini", "r")
if not file then
    error("无法打开 config.ini: " .. err)
end

-- 正常处理
local data = file:read("*all")

-- 立即关闭
file:close()

或者用 pcall + 匿名函数实现类似 try-finally 的效果(高级用法):

local function withFile(filename, mode, callback)
    local f, err = io.open(filename, mode)
    if not f then error(err) end
    local ok, result = pcall(callback, f)
    f:close()
    if not ok then error(result) end
    return result
end

-- 使用
local content = withFile("notes.txt", "r", function(f)
    return f:read("*all")
end)

常见错误与避坑指南

  1. 忘记检查 io.open() 是否成功
    直接对 nil 调用 :read() 会报错:attempt to index a nil value始终先判断文件是否打开成功

  2. 混淆 io.read()file:read()
    io.read() 操作的是标准输入(通常是终端),除非你调用了 io.input(file)优先使用 file:read()

  3. 路径问题
    Lua 使用相对路径时,基准是程序启动时的工作目录,不是脚本所在目录。若需脚本目录下的文件,可用:

    local script_dir = arg[0]:match("(.*[/\\])")
    local filepath = (script_dir or "") .. "myfile.txt"
  4. 二进制文件误用文本模式
    读取图片、音频等二进制文件时,必须使用 "rb" 模式,否则在 Windows 上可能因换行符转换导致数据损坏。

  5. 未处理编码问题
    Lua 默认按字节处理文件,不涉及字符编码。若文件含中文等非 ASCII 字符,读出的是原始字节串。如需 UTF-8 解析,需额外处理(Lua 本身无内置支持)。


完整示例:安全读取整个文件

function readFile(path)
    local file, err = io.open(path, "r")
    if not file then
        return nil, "打开文件失败: " .. tostring(err)
    end

    local content = file:read("*all")
    file:close()

    return content
end

-- 使用
local text, errmsg = readFile("example.txt")
if text then
    print("文件内容长度:", #text, "字节")
else
    print(errmsg)
end

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文