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

lua中的读写文件 lua,read,write,文件 阅读详情

文件读写基础


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
xpcall()带错误处理函数的保护调用,可获取完整栈追踪local status = xpcall(read_file, debug.traceback) print(status)
  • 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()  -- 获取当前位置

完整示例

-- 创建一个测试文件并写入内容
local filePath = "./txt/test1.txt";
local file = io.open(filePath, "w")
if not file then 
    print("无法创建文件");
    return 
end 
 
-- 写入一些测试内容 
file:write("第一行内容\n")
file:write("第二行内容\n") 
file:write("第三行内容\n")
file:close()
 
-- 重新打开文件进行读取操作 
file = io.open(filePath, "r")
if not file then 
    print("无法打开文件")
    return 
end 
 
-- 获取初始位置(文件开头)
local pos = file:seek()
print("初始位置:", pos)  -- 应该输出 0 
 
-- 读取第一行 
local line1 = file:read("*l")
print("读取第一行:", line1)
 
-- 获取当前位置 
pos = file:seek()
print("读取第一行后的位置:", pos)
 
-- 移动到文件开头 
file:seek("set", 0)
pos = file:seek()
print("移动到开头后的位置:", pos)  -- 应该输出 0 
 
-- 再次读取第一行 
local line1_again = file:read("*l")
print("重新读取第一行:", line1_again)
 
-- 移动到文件末尾并获取文件大小 
local fileSize = file:seek("end")
print("文件大小(字节):", fileSize)
 
-- 关闭文件 
file:close()
 
-- 清理测试文件 
os.remove(filePath)

--[[
初始位置:   0
读取第一行:  第一行内容
读取第一行后的位置:  16
移动到开头后的位置:  0
重新读取第一行:    第一行内容
文件大小(字节):   48
]]

2 ) 二进制文件处理

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

-- 完整的二进制文件复制示例 
function copyBinaryFile(sourceFile, destFile)
    -- 1. 打开源文件(二进制读取模式)
    local input, err = io.open(sourceFile, "rb")
    if not input then 
        print("错误:无法打开源文件 " .. sourceFile .. ": " .. err)
        return false 
    end 
    
    -- 2. 读取所有数据 
    local data = input:read("*all")
    input:close()
    
    -- 3. 打开目标文件(二进制写入模式)
    local output, err = io.open(destFile, "wb")
    if not output then 
        print("错误:无法创建目标文件 " .. destFile .. ": " .. err)
        return false 
    end 
    
    -- 4. 写入数据 
    output:write(data)
    output:close()
    
    print("成功复制文件: " .. sourceFile .. " -> " .. destFile)
    print("文件大小: " .. #data .. " 字节")
    return true 
end 
 
-- 使用示例 
copyBinaryFile("./imgs/cover.jpg", "./imgs/target2.jpg");

3 ) 批量读写优化

逐行处理大文件:

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

完整示例:

-- 优化版本:使用缓冲区和批量写入 
local input_file = "./txt/input.txt"
local output_file = "./txt/target.txt"

local input = io.open(input_file, "rb")  -- 二进制模式可能更快 
local output = io.open(output_file, "wb")
 
if not input or not output then 
    print("文件打开失败")
    if input then input:close() end 
    if output then output:close() end 
    return 
end 
 
-- 使用缓冲区减少I/O操作次数 
local buffer = {}
local buffer_size = 1000  -- 每1000行写入一次 
local line_count = 0 
local buffer_count = 0 
 
-- 优化的逐行处理 
for line in input:lines() do 
    line_count = line_count + 1 
    
    -- 示例处理:转换为大写并去除空白 
    local processed = line:upper():gsub("^%s+", ""):gsub("%s+$", "")
    
    -- 添加到缓冲区 
    buffer_count = buffer_count + 1 
    buffer[buffer_count] = processed 
    
    -- 缓冲区满时批量写入 
    if buffer_count >= buffer_size then 
        output:write(table.concat(buffer, "\n") .. "\n")
        buffer = {}  -- 清空缓冲区 
        buffer_count = 0 
        
        -- 显示进度 
        print("已处理 " .. line_count .. " 行")
    end 
end 
 
-- 写入剩余的缓冲区内容 
if buffer_count > 0 then 
    output:write(table.concat(buffer, "\n"))
end 
 
input:close()
output:close()
 
print("优化处理完成!总计处理 " .. line_count .. " 行")

-- 优化处理完成!总计处理 3 行

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

学习总结与建议

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

Lua语言的文件操作 Lua语言的文件操作功能强大而灵活,能够满足大多数应用场景的需求。从文件的打开、读取、写入、关闭到异常处理,Lua提供了简单易用的接口。我们在进行文件操作时,应注意文件路径、编码和权限等问题,以确保程序稳定运行。通过本文的介绍,希望能够帮助读者更好地理解和掌握Lua语言的文件操作技巧。 阅读详情

相关推荐

C++调用lua函数及lua_pcall的错误处理示例

看过上一篇文章lua与C++交互—配置文件就知道C++是怎么获取lua里边的变量了,实际上用C++调用lua函数也与此类似。首先要获得lua函数的地址,然后我们通过栈将函数需要的参数传递给lua,然后运行该函数,函数会将运行结果压入栈,我们再从栈中取出结果即可。 一、定义lua函数 在lua文件里面我们写一个简单的加法函数。 //config.lua文件内容 function myadd(a,b)...

yulijuanxmu的博客 2859

Lua读写文件

lua里的文件读写模型来自C语言,分为完整模型(和C一样)、简单模型。 1、简单模型 io.input([file]) 设置默认的输入文件,file为文件名(此时会以文本读入)或文件句柄(可以理解为把柄,有了把柄就可以找到文件),返回文件句柄。 io.output([file]) 设置默认的输出文件,参数意义同上。 io.close([file]) 关闭文件,不带参数关闭默认的文件 io.read(formats) 读入默认文件,formats取值为"*a"(读入全部)、“*n”(按数字读入)、 "..

qq_39025293的博客 5306

Lua脚本使用教学指南:与Spring Boot项目集成示例

Lua由巴西里约热内卢天主教大学(PUC-Rio)于1993年开发,设计目标是轻量、高效、可嵌入。Lua的核心非常小巧,但功能强大,支持面向过程、面向对象和函数式编程。通过本指南,你不仅学习了Lua的基础语法和高级特性,还掌握了如何将Lua脚本与Spring Boot项目集成。Lua的轻量级和灵活性使其成为动态逻辑处理的理想选择,而Spring Boot的强大功能则为Java应用提供了坚实的基础。

格子先生Lab的博客 1856

Lua开发--文件读写操作

lua文件处理有两种模式: 简单模式:拥有一个当前输入文件和一个当前输出文件,并且提供针对这些文件相关的操作,适用于简单的文件操作 完全模式:使用外部的文件句柄来实现。它以一种面对对象的形式,将所有的文件操作定义为文件句柄的方法,适用于高级文件操作,例如同时读取多个文件 简单模式 file = io.open (filename [, mode]) mode 作用 r 读,文件不存在则报错 w 写,若文件存在则覆盖重写,若文件不存在则新建 a 写,若文件不存在,则新建;如果文件

liulanba的博客 1万+

【Lua从青铜到王者基础篇】第十二篇:Lua错误处理

系列文章目录 文章目录系列文章目录前言一、Lua 错误处理二、语法错误三、运行错误四、错误处理1.error函数2.pcall函数3.xpcall函数4.debug函数 总结 前言 一、Lua 错误处理 程序运行中错误处理是必要的,在我们进行文件操作,数据转移及web service 调用过程中都会出现不可预期的错误。如果不注重错误信息的处理,就会造成信息泄露,程序无法运行等情况。 任何程序语言中,都需要错误处理。错误类型有: 语法错误。 运行错误。 简单模式在做一.

森明帮大于黑虎帮的博客 2107

Lua错误处理与调试

Lua提供了xpcall函数,xpcall接收第二个参数——一个错误处理函数,当错误发生时,Lua会在调用桟展看(unwind)前调用错误处理函数,于是就可以在这个函数中使用debug库来获取关于错误的额外信息了。使用简单的命令以及其它调试设置,用户可以检阅全局变量和局部变量, 改变变量的值,计算一些表达式,等等。在以实例中,我们使用到了 debug 库的 traceback 和 getinfo 函数, getinfo 函数用于返回函数信息的表。如果函数没有那个上值,返回 nil 否则,返回该上值的名字。

悦分享 1409

lua服务器读写文件,Openresty+Lua 读写文件

Talk is cheap. Show me the code.因为 lua 写读写操作比较麻烦,所以大致封装了一下。读文件:-- 读文件-- 参数:需要读取的文件路径-- 返回值:读出的内容,读取错误。-- 如果没有读出内容,第一个参数为 nil,否则第二个参数为 nillocal function read_file(file_name)if not file_name thenreturn ...

weixin_35854667的博客 1125

Lua与C语言交互的实用指南及示例

Lua标准库是Lua语言的核心部分,它为程序员提供了丰富的功能,包括字符串处理、表操作、数学计算等。熟悉并有效使用标准库中的模块,是编写高效且可维护Lua代码的关键。

weixin_36178216的博客 1107

Lua 错误处理

Lua 提供了完善的错误处理机制,包括语法错误和运行错误的检测与处理。核心函数如 assert、error、pcall 和 xpcall 能够有效捕获和处理异常,适用于参数验证、文件操作等场景。调试工具如 debug.debug 和 debug.traceback 可帮助定位错误。最佳实践建议在开发阶段充分验证参数并合理使用保护调用,确保程序稳定性。更多详情可参考菜鸟教程、w3cschool 等中文资源。

likuoelie的博客 1466

立创EDA手动拼板实战:当自带功能不够用,如何用‘复制粘贴’搞定异形拼版与特殊布局

本文详细介绍了立创EDA手动拼板技术在异形拼版与特殊布局中的应用实战。通过CTRL+SHIFT+V等核心操作技巧,解决混合尺寸拼板、特殊间距需求等复杂场景,提升PCB设计效率与灵活性,特别适合需要高精度控制的射频电路和医疗设备项目。

weixin_31967485的博客 390

灯塔问题:贪心与动态规划算法解析

区间覆盖问题是算法设计中的经典案例,常用于理解贪心算法与动态规划的核心差异。贪心算法通过局部最优选择逐步构建全局解,具有O(n log n)的高效时间复杂度,特别适合处理一维区间覆盖场景。动态规划则采用自底向上的填表法,虽然通用性更强但复杂度较高。在实际工程中,这类算法广泛应用于无线基站部署、监控设备布置等资源优化场景。通过分析灯塔问题的两种解法,可以深入掌握算法选择的关键因素,如问题规模、性能要求和实现复杂度。

weixin_28720573的博客 260

lua_pcall详解

用法 lua_pcall(lua_State *L,int nargs,int nresults,int errfunc) nargs 参数个数 nresults 返回值个数 errFunc 错误处理函数,0表示无,表示错误处理函数在栈中的索引 --test.lua function test(x,y) return x + y end lua_loadfile(L,"test...

auspark的专栏 1万+

【Docker】Docker安装Hadoop分布式集群

hadoop目录安装在:/usr/local/hadoop-2.7.0/etc/hadoop。访问Hadoop102:9870,查看是否能够看到hdfs界面。访问hadoop103:8088,查看能够看到yarn界面。在yarn上可以看到执行情况。

weixin_46429290的博客 3462

lua文件操作详解例子解析

这些是Lua文件操作的一些基本示例。在实际应用中,可以根据需求选择合适的模式和方法来进行文件的读写操作。记得始终在完成操作后关闭文件,以确保数据的完整性和系统的稳定性。Lua文件操作是编程中常见的任务,Lua提供了一套简单易用的I/O库来处理文件。模式可以是"r"(只读),“w”(写入,覆盖现有内容),“a”(追加),“r+”(读写),等等。函数打开文件,它接受两个参数:文件名和模式。方法设置文件指针的位置。在打开文件时,如果操作失败,一旦文件被打开,可以使用。完成文件操作后,应使用。

IT老农民的博客 1183

2025_NIPS_RAGRouter: Learning to Route Queries to Multiple Retrieval-Augmented Language Models

该研究聚焦检索增强生成(RAG)场景下的大语言模型(LLM)路由问题,提出了首个RAG感知的路由框架RAGRouter。核心解决现有路由方法依赖静态参数知识、忽略检索文档动态影响的缺陷,通过融合文档嵌入、RAG能力嵌入与对比学习,捕捉RAG引发的模型知识表征变化,为每个查询-文档对选择最优LLM。实验覆盖5个知识密集型任务、15个开源/闭源LLM,验证了RAGRouter在性能上超越最佳单LLM和非RAG感知路由方法,且通过阈值机制实现低延迟约束下的性能-效率平衡。

UnknownBody_2的博客 274

46.qt quick-自定义非常好看的qml虚拟软键盘-支持换肤、动态加载移除语言(二)

在上章我们学习了45.qt quick-qml虚拟软键盘详解(一)_诺谦的博客-优快云博客 接下来我们便来自定义一款好看的qml软键盘.如下图所示: 支持背景更换、支持动图: 支持动态加载移除语言: 支持拖拽、自由缩小放大: 支持定位坐标: ...

抵抗时间扭曲,坚持做一件有意义的事 4675
上一篇: Lua: 面向对象编程详解之类、继承、封装与多态实现
下一篇: Lua: 错误处理与调试技术详解之从基础到EmmyLua高级调试
Wang's Blog
博客等级 码龄12年 7438粉丝 2422原创
评论
成就一亿技术人!
拼手气红包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、付费专栏及课程。

余额充值