Skip to content

📁 文件操作库 - 简单易懂的文件处理指南 ​

📖 什么是文件操作? ​

文件操作就像使用记事本一样,可以打开文件、读取内容、写入内容、保存文件。程序可以通过文件来保存数据、读取配置、记录日志等。

能做什么:

  • 📖 读取文件(比如读取配置文件)
  • ✏️ 写入文件(比如保存数据到文件)
  • 📝 追加内容(比如往日志文件添加新记录)
  • 📂 检查文件是否存在
  • 📄 获取文件信息

实际应用:

  • 读取设备配置文件
  • 保存采集到的数据
  • 记录运行日志
  • 导出报表文件
  • 备份重要数据

🚀 3分钟快速上手 ​

示例1: 文本文件操作(写入,读取,删除操作) ​

lua
local file_path = "/spiffs/example.txt"-- 文件路径(可替换为实际路径)WIFI版PLC文件名必须“/spiffs/”开头,wifi版只有这一个目录可用,如果不存在目录将失败
-- 写入文件示例
local function write_file()
    local file = io.open(file_path, "w")-- 以写入模式打开文件(若文件存在则覆盖)
    if not file then
        print("无法打开文件进行写入")
        return
    end
    -- 写入多行内容
    file:write("这是第一行文本\n")
    file:write("第二行包含数字: ", 123, "\n")
    file:write("第三行使用格式化: %s - %d\n", "Lua", 5.3)
    file:close()-- 关闭文件句柄
    print("文件写入完成")
end

-- 读取文件示例
local function read_file()
    local file = io.open(file_path, "r")-- 以读取模式打开文件
    if not file then
        print("无法打开文件进行读取")
        return
    end
    -- 逐行读取并打印
    print("\n文件内容:")
    for line in file:lines() do
        print(line)
    end
    file:close()-- 关闭文件
end

-- 执行写入和读取操作
write_file()
read_file()

-- 追加写入示例
local function append_file()
    local file = io.open(file_path, "a")  -- 追加模式
    if file then
        file:write("\n这是追加的内容\n")
        file:close()
    end
end

append_file()
print("\n追加后再次读取:")
read_file()

-- 删除文件函数(带错误处理)
local function delete_file()
    -- 检查文件是否存在(可选,更高效的方式)
    local file = io.open(file_path, "r")
    if not file then
        print("文件不存在,无需删除")
        return false
    end
    file:close()

    -- 执行删除操作
    local success, err = os.remove(file_path)
    if success then
        print("文件删除成功")
        return true
    else
        print("文件删除失败:", err)
        return false
    end
end
delete_file()       -- 删除文件
delete_file()       -- 再次尝试删除(测试文件不存在的情况)

示例2: 二进制文件操作(写入,读取) ​

lua
local filename = "/spiffs/example.bin"-- 文件路径(可替换为实际路径)
-- 写入二进制文件示例
local function write_binary()
    local file = io.open(filename, "wb")  -- 二进制写入模式
    if not file then
        error("无法创建文件: " .. filename)
    end
    -- 写入固定结构数据
    file:write(string.pack(">I4", 0x12345678))       -- 4字节大端整数
    file:write(string.pack(">d", 3.1415926535))      -- 8字节双精度浮点
    file:write(string.char(0xAB, 0xCD, 0xEF))        -- 自定义字节序列
    file:close()
    print("二进制文件写入完成")
end
write_binary()-- 执行写入操作
-- 读取二进制文件示例
local function read_binary()
    local file = io.open(filename, "rb")  -- 二进制读取模式
    if not file then
        error("无法打开文件: " .. filename)
    end
    -- 读取并解析数据
    local int_data = file:read(4)  -- 读取4字节
    local num = string.unpack(">I4", int_data)
    print("大端整数: 0x" .. string.format("%X", num))  -- 输出: 0x12345678
    local float_data = file:read(8)
    local pi = string.unpack(">d", float_data)
    print("圆周率: " .. string.format("%.9f", pi))     -- 输出: 3.141592654
    local bytes = file:read(3)
    print("字节序列: " .. string.byte(bytes, 1, 3))    -- 输出: 171
    file:close()
end
read_binary()-- 执行读取操作

📚 API参考 ​

📋 函数列表 ​

函数名功能描述示例
io.open(filename, [mode])打开文件io.open("file.txt", "r")
io.close([file])关闭文件io.close(file)
📖 io.read(...)从标准输入读取io.read("*line")
✏️ io.write(...)写入到标准输出io.write("Hello")
🔄 io.flush()刷新标准输出缓冲区io.flush()
📥 io.input([file])设置或获取默认输入文件io.input("data.txt")
📤 io.output([file])设置或获取默认输出文件io.output("log.txt")
io.lines([filename, ...])逐行迭代文件内容io.lines("file.txt")
io.popen(prog, [mode])启动程序并连接到其输入/输出io.popen("ls")
io.tmpfile()创建临时文件io.tmpfile()
io.type(obj)检查对象是否为有效的文件句柄io.type(file)
file:read(...)从文件读取file:read("*all")
file:write(...)写入到文件file:write("data")
file:lines(...)逐行迭代文件内容file:lines()
file:flush()刷新文件缓冲区file:flush()
file:seek([whence, offset])设置或获取文件位置file:seek("set", 0)
file:setvbuf(mode, [size])设置文件缓冲模式file:setvbuf("no")
file:close()关闭文件file:close()

📦 io.open(filename, [mode]) ​

打开文件

参数:

  • filename (string): 文件名
  • mode (string, 可选): 打开模式
    • "r": 只读(默认)
    • "w": 只写(创建新文件或清空现有文件)
    • "a": 追加(文件末尾写入)
    • "r+": 读写(文件必须存在)
    • "w+": 读写(创建新文件或清空现有文件)
    • "a+": 读写(追加模式)
    • "rb", "wb", "ab": 二进制模式

返回值:

  • file: 文件对象,失败返回nil

示例:

lua
-- 读取文件
local file = io.open("/spiffs/config.txt", "r")
if file then
    local content = file:read("*all")
    print(content)
    file:close()
else
    print("无法打开文件")
end

-- 写入文件
local file = io.open("/spiffs/output.txt", "w")
if file then
    file:write("Hello World\n")
    file:close()
end

-- 二进制文件操作
local bin_file = io.open("/spiffs/data.bin", "rb")
if bin_file then
    local data = bin_file:read(1024)  -- 读取1024字节
    bin_file:close()
end

实用例程 ​

lua
local function file_write(file_path, file_data)
	print("<名称>"..file_path)
    local file = io.open(file_path, "w")-- 以写入模式打开文件(若文件存在则覆盖)
    if not file then
        print("<名称>")
        return
		end
    file:write(file_data)
    file:close()-- 关闭文件句柄
    print("<名称>")
end

local function file_read(file_path, file_data)
	print("<名称>"..file_path)
    local file = io.open(file_path, "r")-- 以读取模式打开文件
	local file_data = file:read("*a") 
	file:close()-- 关闭文件
	system.sleep(10)
	local success, err = os.remove(file_path)
    if success then
        print("文件删除成功")
		else
        print("文件删除失败:", err)
		end
	return file_data
end

-- 删除文件函数(带错误处理)

把上面的地址、主题、引脚替换成你项目里的即可。

📦 io.close([file]) ​

关闭文件

参数:

  • file (file, 可选): 文件对象,默认为标准输出文件

返回值:

  • boolean: 成功返回true,失败返回nil
  • string: 错误信息(失败时)

示例:

lua
-- 关闭特定文件
local file = io.open("/spiffs/data.txt", "r")
if file then
    -- 读取文件内容
    local content = file:read("*all")
    -- 关闭文件
    local success, err = io.close(file)
    if success then
        print("文件已关闭")
    else
        print("关闭文件失败:", err)
    end
end

-- 关闭默认输出文件
io.output():write("一些数据\n")
io.close()  -- 关闭默认输出文件

📋 io.lines([filename, ...]) ​

逐行迭代文件内容

参数:

  • filename (string, 可选): 文件名
  • ... (可选): 读取格式参数

返回值:

  • function: 迭代器函数

示例:

lua
-- 迭代文件的每一行
for line in io.lines("/spiffs/data.txt") do
    print("行内容:", line)
end

-- 使用不同的读取格式
for line in io.lines("/spiffs/data.txt", "*line") do
    print("行:", line)
end

📄 io.tmpfile() ​

创建临时文件

返回值:

  • file: 临时文件对象

示例:

lua
-- 创建临时文件
local tmp = io.tmpfile()
tmp:write("临时数据\n")
tmp:seek("set", 0)  -- 回到文件开始
local content = tmp:read("*all")
print("临时文件内容:", content)
-- 临时文件在程序结束时自动删除

🔍 io.type(obj) ​

检查对象是否为有效的文件句柄

参数:

  • obj (any): 要检查的对象

返回值:

  • "file": 开启的文件句柄
  • "closed file": 已关闭的文件句柄
  • nil: 不是文件句柄

示例:

lua
local file = io.open("/spiffs/data.txt", "r")
print(io.type(file))  -- "file"

file:close()
print(io.type(file))  -- "closed file"

print(io.type("not a file"))  -- nil
print(io.type(123))  -- nil

📖 file:read(...) ​

从文件读取

参数:

  • "*all": 读取整个文件
  • "*line": 读取一行
  • "*number": 读取一个数字
  • number: 读取指定字节数

返回值:

  • string/number: 读取的内容,失败返回nil

示例:

lua
local file = io.open("/spiffs/data.txt", "r")
if file then
    -- 逐行读取
    for line in file:lines() do
        print("行:", line)
    end
    file:close()
end

✏️ file:write(...) ​

写入到文件

参数:

  • ... (string/number): 要写入的内容

返回值:

  • file: 文件对象

示例:

lua
local file = io.open("/spiffs/log.txt", "a")
if file then
    file:write(os.date(), " - 系统启动\n")
    file:close()
end

📦 file:close() ​

关闭文件

返回值:

  • boolean: 成功返回true,失败返回nil
  • string: 错误信息(失败时)

示例:

lua
local file = io.open("/spiffs/data.txt", "r")
if file then
    -- 读取文件内容
    local content = file:read("*all")
    print(content)
    
    -- 关闭文件
    local success, err = file:close()
    if success then
        print("文件已关闭")
    else
        print("关闭文件失败:", err)
    end
end

📋 file:lines(...) ​

逐行迭代文件内容

参数:

  • ... (可选): 读取格式参数

返回值:

  • function: 迭代器函数

示例:

lua
local file = io.open("/spiffs/data.txt", "r")
if file then
    -- 迭代文件的每一行
    for line in file:lines() do
        print("行内容:", line)
    end
    file:close()
    
    -- 使用不同的读取格式
    file = io.open("/spiffs/numbers.txt", "r")
    if file then
        for number in file:lines("*number") do
            print("数字:", number)
        end
        file:close()
    end
end

🔄 file:flush() ​

刷新文件缓冲区

示例:

lua
local file = io.open("/spiffs/log.txt", "w")
if file then
    file:write("日志条目1\n")
    file:flush()  -- 确保数据写入磁盘
    
    file:write("日志条目2\n")
    file:flush()  -- 确保数据写入磁盘
    
    file:close()
end

📍 file:seek([whence, offset]) ​

设置或获取文件位置

参数:

  • whence (string, 可选): 参考位置
    • "set": 文件开始(默认)
    • "cur": 当前位置
    • "end": 文件末尾
  • offset (number, 可选): 偏移量,默认为0

返回值:

  • number: 新的位置
  • nil: 失败
  • string: 错误信息(失败时)

示例:

lua
local file = io.open("/spiffs/data.txt", "r")
if file then
    -- 获取当前位置
    local pos = file:seek()
    print("当前位置:", pos)  -- 0
    
    -- 读取一些数据
    local data = file:read(10)
    pos = file:seek()
    print("读取后位置:", pos)  -- 10
    
    -- 移动到文件开始
    file:seek("set", 0)
    pos = file:seek()
    print("回到开始位置:", pos)  -- 0
    
    -- 从当前位置向前移动5个字节
    file:seek("cur", 5)
    
    -- 移动到文件末尾
    local end_pos = file:seek("end")
    print("文件末尾位置:", end_pos)
    
    file:close()
end

⚙️ file:setvbuf(mode, [size]) ​

设置文件缓冲模式

参数:

  • mode (string): 缓冲模式
    • "no": 无缓冲
    • "full": 全缓冲
    • "line": 行缓冲
  • size (number, 可选): 缓冲区大小

示例:

lua
local file = io.open("output.txt", "w")
if file then
    -- 设置为无缓冲模式(立即写入)
    file:setvbuf("no")
    file:write("立即写入的数据\n")
    
    -- 设置为行缓冲模式
    file:setvbuf("line")
    file:write("行缓冲数据")
    file:write("\n")  -- 这会触发写入
    
    -- 设置为全缓冲模式,指定缓冲区大小
    file:setvbuf("full", 1024)
    file:write("全缓冲数据...")
    
    file:close()
end

🚀 io.popen(prog, [mode]) ​

启动程序并连接到其输入/输出

参数:

  • prog (string): 程序命令
  • mode (string, 可选): 模式("r"或"w")

返回值:

  • file: 文件对象

示例:

lua
-- 读取系统命令输出
local file = io.popen("ls -l")
if file then
    local output = file:read("*all")
    print(output)
    file:close()
end

-- 向命令写入数据
local file = io.popen("sort", "w")
if file then
    file:write("banana\napple\ncherry\n")
    file:close()
end

例程 ​

⚠ 文件库(io.*)需要文件系统支持:仅软PLC模拟器 / 上位机 可用;嵌入式固件(LP3201/LP3202/LP3203/LP3222/LP3232/LP3288 等)通常没有文件系统,io.open 会返回 nil。下面例程在模拟器/上位机里可直接下载运行,在嵌入式上请改用 fdb/ini 等内置存储模块。

例程 1:读取配置文件并逐行解析 ​

适用:软PLC模拟器 / 上位机 | 依赖模块:io string | 难度:★☆☆

场景:从 /spiffs/config/device.ini 读一份 key=value 配置,解析成表供脚本使用。

完整代码(可直接下载运行):

lua
local cfg = {}
local f = io.open("/spiffs/config/device.ini", "r")
if not f then
    print("配置文件不存在,使用默认值")
else
    for line in f:lines() do
        local k, v = line:match("^([%w_]+)%s*=%s*(.+)$")
        if k then cfg[k] = v end
    end
    f:close()
end
print("设备名 =", cfg.device_name or "未配置")

要点:

  • io.open(path, "r") 读模式;失败返回 nil + 错误信息,必须先判空再使用。
  • f:lines() 逐行迭代,省内存;用完 f:close() 释放句柄(句柄数量有限)。
  • 用 string.match 拆 key=value,比 string.gmatch 更适合单行。

验证方法:

  1. 在模拟器 /spiffs/config/device.ini 写 device_name=Line-A,运行打印「设备名 = Line-A」。
  2. 删掉文件,运行打印「配置文件不存在,使用默认值」「设备名 = 未配置」且不崩溃。

注意事项:

  • 嵌入式固件无文件系统,io.open 永远返回 nil;别在固件脚本里依赖它。
  • 忘记 f:close() 会耗尽文件句柄,下次 open 失败。
  • 路径大小写、目录是否存在因平台而异;WIFI 版文件名必须 /spiffs/ 开头。

例程 2:追加写运行日志 ​

适用:软PLC模拟器 / 上位机 | 依赖模块:io os | 难度:★☆☆

场景:把每次报警/事件带时间戳追加到日志文件,重启后仍在。

完整代码(可直接下载运行):

lua
local log_path = "/spiffs/run.log"
local function log_event(msg)
    local f = io.open(log_path, "a")   -- "a" = 追加,文件不存在则新建
    if not f then print("无法写日志:", msg) return end
    f:write(os.date("%Y-%m-%d %H:%M:%S"), " ", msg, "\n")
    f:close()
end

log_event("设备启动")
log_event("温度越限 82.3")

要点:

  • 模式 "a" 追加(不覆盖历史);"w" 会清空原文件,慎用。
  • 每行以 \n 结尾,方便后续按行读取。
  • 用 os.date 打时间戳,便于排查。

验证方法:

  1. 运行两次,日志文件出现两行带时间戳的记录。
  2. 把模式改成 "w" 再跑:原内容被清空,只剩最后一条。

注意事项:

  • 频繁 open/close 写小日志效率差;高频日志建议攒一批用 table.concat 一次性写。
  • 日志无限增长会撑满存储,生产环境要按大小/时间滚动或只保留最近 N 行。
  • 写失败(磁盘满/只读)io.open 返回 nil,务必判空。

例程 3:导出 CSV 数据文件 ​

适用:软PLC模拟器 / 上位机 | 依赖模块:io table string | 难度:★★☆

场景:把采集的温度点导出成 time,value 的 CSV,方便上位机拉走分析。

完整代码(可直接下载运行):

lua
local rows = {
    { "2026-09-25 08:00", 25.6 },
    { "2026-09-25 09:00", 26.1 },
    { "2026-09-25 10:00", 24.8 },
}

local f = io.open("/spiffs/temp.csv", "w")
if f then
    f:write("time,value\n")
    for _, r in ipairs(rows) do
        f:write(r[1], ",", string.format("%.1f", r[2]), "\n")
    end
    f:close()
    print("已导出", #rows, "行")
end

要点:

  • 先写表头 time,value\n,再逐行 时间,数值\n。
  • 数值用 string.format("%.1f", v) 固定小数位,避免 CSV 里出现 25.60000001 这类浮点尾。
  • 关闭前内容可能在缓冲区,不 close 可能丢最后几行。

验证方法:

  1. 运行后 /spiffs/temp.csv 内容为 3 行数据 + 表头。
  2. 把 rows 清空再跑:只剩表头一行,不报错。

注意事项:

  • 忘记 f:close() 可能导致末尾数据未落盘。
  • 用 .. 在循环里拼超大 CSV 很慢且费内存,用 table.concat 攒好再一次性 write。
  • 嵌入式固件不支持,需改用 fdb 模块或上位机中转。

最后更新: 2026-04-26版本: 1.0

函数速查表 ​

下表列出本库全部函数与方法(含尚未单独成节的),点「说明」可跳转到对应小节。签名按通用记法:括号内按顺序列全参数,方括号里的可以省略(不传走默认值),... 表示还可继续传同类参数;h: 开头的是对象方法,先用库级函数拿回句柄再冒号调用。

方法与签名作用说明
io.close(…)关闭文件句柄本文开头
io.flush(…)把缓冲区内容立即写入文件本文开头
io.input(…)设置默认输入文件跳转
io.lines(string)按行迭代读取文件本文开头
io.open(string)打开文件(r 读 / w 写 / a 追加,加 + 可双向)本文开头
io.output(…)设置默认输出文件本文开头
io.popen(string)执行一条命令并返回可读其输出的句柄本文开头
io.read(…)从文件读取内容本文开头
io.tmpfile(…)打开一个临时文件本文开头
io.type(...)检查是否为有效文件句柄本文开头
io.write(…)向文件写入内容本文开头

io.input ​

  • 作用:设置默认输入文件
  • 调用形态:io.input(…)(库级函数)
  • 参数:无参数
  • 可用机型:软 PLC 模拟器 / 上位机

LPPLC 工业物联网云平台 · 软硬件与云平台全栈自研