Lua: 文件读写与错误处理详解及实战示例

文件读写基础


1 ) 文件打开 (io.open)

功能:创建文件句柄,指定访问模式

模式功能说明适用场景
r只读模式,默认值,文件需存在读取配置文件、日志文件
w覆盖写入模式,不存在则新建生成全新输出文件、覆盖备份
a追加写入模式日志追加、内容补充
r+读写模式,文件需存在编辑现有文件内容
w+读写模式,清空原有内容创建可编辑的临时文件
a+读写追加模式同时读取旧内容并追加新内容
rb/wb二进制读写模式处理图片、音频等二进制文件

模式参数:

  • "r":只读(默认)
  • "w":写入(覆盖原内容)
  • "a":追加(文件末尾写入)
  • "r+":读写更新(保留原数据)
  • "b":二进制模式(如 “rb”)
local file = io.open("test.txt", "r")  -- 只读模式打开
assert(file, "文件打开失败!")         -- 结合assert检查错误

2 ) 文件读取 (file:read)

读取选项:

  • "*a":读取整个文件
  • "*l":读取一行(默认)
  • "*n":读取一个数字
  • n:读取n个字节(如 file:read(10)
local content = file:read("*a")  -- 读取全部内容 

3 ) 文件写入 (file:write)

写入字符串或数据到文件

local file = io.open("log.txt", "a")  -- 追加模式
file:write("New log entry\n")        -- 写入一行

4 ) 关闭文件 (file:close)

释放资源,避免内存泄漏

 file:close()  -- 显式关闭文件

文件读写核心代码


以下为可直接运行的基础操作示例:

1 ) 读取文件全部内容

--- 以只读模式打开文件,使用assert捕获打开异常 
local file = assert(io.open("test.txt", "r"), "文件打开失败,请检查路径是否正确") 
--- 一次性读取文件所有内容 
local content = file:read("*a") 
print("读取到的文件内容:") 
print(content) 
file:close() 

2 ) 写入并追加文件内容

--- 以覆盖模式打开文件,不存在则自动创建 
local file = assert(io.open("output.txt", "w")) 
file:write("Hello Lua 文件写入测试\n") 
file:close() 
--- 追加内容到文件末尾 
local append_file = assert(io.open("output.txt", "a")) 
append_file:write("追加第二行测试内容") 
append_file:close() 

错误处理机制


1 ) 语法错误检查

常见错误:运算符误用(如 = 与 ==)、缺少关键字(如 for 循环缺 do)

for i = 1, 10 do  -- 正确:循环体需用 do ... end
  print(i)
end

2 ) 运行时错误捕获

核心函数用法对照如下:

函数功能描述代码示例
assert()校验条件,不满足则抛出指定错误信息assert(type(count) == “number”, “count 必须为数字类型”)[[8]]
error()主动抛出错误,可指定错误层级if not file then error(“文件操作执行失败”, 2) end[[14]]
pcall()保护模式调用函数,捕获错误不终止程序local ok, err = pcall(file.read, file) if not ok then print(“读取错误:”, err) end[[3]]
xpcall()带错误处理函数的保护调用,可获取完整栈追踪local status = xpcall(read_file, debug.traceback) print(status)[[3]]
  • assert(condition, message):条件为假时抛出错误

    local num = "abc"
    assert(type(num) == "number", "非数字类型!")  -- 抛出错误
    
  • pcall(func, …):保护模式调用函数,返回状态和错误信息

    local success, err = pcall(function()
        error("自定义错误")
    end)
    if not success then print("错误:", err) end
    
  • xpcall(func, err_handler):提供自定义错误处理函数

    local function handle_err(err)
        print("错误详情:", debug.traceback(err))
    end
    xpcall(errorfunction, handleerr)
    

3 )文件操作中的错误处理

结合 assert 与 io.open 确保文件有效:

local file, err = io.open("missing.txt", "r")
if not file then 
    print("打开失败:", err)  -- 输出错误信息
    return
end

完整示例:文件复制(含错误处理)

--- 安全复制文件
local function copyfile(srcpath, dst_path)
	-- 打开源文件(带错误检查)
    local src, err = io.open(src_path, "rb")
    if not src then
        return false, "源文件打开失败: " .. err
    end
	-- 读取内容
    local content, read_err = src:read("*a")
    if not content then
        src:close()
        return false, "读取失败: " .. (read_err or "未知错误")
    end
    src:close()
	--- 写入目标文件
    local dst, openerr = io.open(dstpath, "wb")
    if not dst then
        return false, "目标文件创建失败: " .. open_err
    end
    dst:write(content)
    dst:close()
    return true, "复制成功"
end
-- 执行复制并处理结果
local ok, msg = copy_file("source.txt", "target.txt")
print(ok and "成功" or "失败", msg)

工程示例


1 ) 示例1

--- 1. 读取文件内容 
function readFile(filename)
    local file, err = io.open(filename, "r")
    if not file then
        print("错误: 无法打开文件 " .. filename .. " - " .. err)
        return nil
    end
    local content = file:read("*a") -- 读取所有内容 
    file:close()
    return content
end
--- 2. 写入文件内容(覆盖)
function writeFile(filename, content)
    local file, err = io.open(filename, "w")
    if not file then
        print("错误: 无法打开文件 " .. filename .. " - " .. err)
        return false
    end
    file:write(content)
    file:close()
    return true 
end
--- 3. 追加内容到文件
function appendToFile(filename, content)
    local file, err = io.open(filename, "a")
    if not file then
        print("错误: 无法打开文件 " .. filename .. " - " .. err)
        return false
    end 
    file:write(content)
    file:close()
    return true 
end
--- 使用示例
local data = readFile("input.txt")
if data then
    print("文件内容: " .. data)
    appendToFile("output.txt", "追加内容\n")
end 
writeFile("output.txt", "新内容覆盖\n")

2 ) 示例2

--- 1. 使用 assert 检查参数 
function divide(a, b)
    assert(type(a) == "number", "第一个参数必须是数字")
    assert(type(b) == "number", "第二个参数必须是数字")
    assert(b ~= 0, "除数不能为零")
    return a / b
end

--- 2. 使用 pcall 捕获错误 
function safeCall(fn, ...)
    local status, result = pcall(fn, ...)
    if status then 
        print("函数执行成功,结果: " .. tostring(result))
        return result 
    else
        print("函数执行出错: " .. result)
        return nil
    end 
end

--- 3. 使用 xpcall 捕获错误并获取堆栈信息
function detailedCall(fn, ...)
    local status, result = xpcall(fn, debug.traceback, ...)
    if status then 
        print("函数执行成功,结果: " .. tostring(result))
        return result
    else 
        print("函数执行出错,详细信息:\n" .. result)
        return nil
    end
end

--- 使用示例
safeCall(divide, 10, 2) -- 成功
safeCall(divide, 10, 0) -- 出错,被捕获
detailedCall(divide, "string", 5) -- 出错,带堆栈信息

3 )示例3

-- 安全读取文件(带错误处理)
function safeReadFile(filename)
    local file, err = io.open(filename, "r")
    if not file then
        print("错误: 打开文件失败 - " .. err)
        return nil
    end 
 
    local content, readErr = file:read("*a")
    if not content then
        print("错误: 读取文件失败 - " .. readErr)
        file:close()
        return nil
    end
 
    file:close()
    return content 
end
-- 安全写入文件(带错误处理)
function safeWriteFile(filename, content)
    local file, err = io.open(filename, "w")
    if not file then
        print("错误: 创建/打开文件失败 - " .. err)
        return false
    end
 
    local status, writeErr = file:write(content)
    if not status then 
        print("错误: 写入文件失败 - " .. writeErr)
        file:close()
        return false
    end
 
    file:close()
    return true 
end
-- 使用示例 
local data = safeReadFile("config.txt")
if data then
    print("读取成功: " .. data)
else 
    print("读取失败,使用默认配置")
    safeWriteFile("config.txt", "default_setting=true\n")
end

进阶技巧


1 ) 文件定位 (file:seek)

移动读写位置:

file:seek("set", 0)  -- 移动到文件开头
local pos = file:seek()  -- 获取当前位置

2 ) 二进制文件处理

使用 “b” 模式读写非文本文件(如图片)

3 ) 批量读写优化

逐行处理大文件:

for line in file:lines() do  -- 迭代读取每行
    process(line)
end

建议结合调试工具(如 debug.traceback)定位复杂错误

学习总结与建议

1 ) 所有文件操作完成后必须调用file:close()释放系统资源,避免内存泄漏
2 ) 开发阶段优先使用assert()快速校验参数与文件状态,简化代码冗余
3 ) 生产环境中建议搭配xpcall()与debug库记录完整错误栈,便于后续问题排查

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值