On this page

Lua 文件 I/O

Lua 文件 I/O 操作详解

Lua 提供了丰富的文件操作功能,支持文本和二进制文件的读写操作。以下是 Lua 文件 I/O 的全面指南:

1. 文件打开模式

模式描述
"r"只读(默认)
"w"只写(覆盖已有内容)
"a"追加
"r+"读写(文件必须存在)
"w+"读写(创建/覆盖文件)
"a+"读写(追加模式)
"b"二进制模式(与上述组合)

2. 基本文件操作

打开文件

local file = io.open("test.txt", "r")
if not file then
    error("无法打开文件")
end

关闭文件

file:close()

使用完自动关闭(推荐)

local file = assert(io.open("test.txt", "r"))
do
    -- 文件操作
end
file:close()

3. 文件读取

逐行读取

-- 方法1:使用文件句柄
for line in file:lines() do
    print(line)
end

-- 方法2:使用io.lines
for line in io.lines("test.txt") do
    print(line)
end

读取特定内容

local content = file:read("*a")  -- 读取全部内容
local line = file:read("*l")     -- 读取一行(默认)
local number = file:read("*n")   -- 读取一个数字
local chars = file:read(5)       -- 读取5个字符

4. 文件写入

基本写入

local out = assert(io.open("output.txt", "w"))
out:write("Hello, Lua!\n")
out:write(string.format("Value: %d\n", 42))
out:close()

追加内容

local log = assert(io.open("log.txt", "a"))
log:write(os.date() .. " - 日志条目\n")
log:close()

5. 文件位置操作

获取当前位置

local pos = file:seek()  -- 返回当前位置(字节数)

设置位置

file:seek("set", 10)  -- 从文件开头移动10字节
file:seek("cur", -5)  -- 从当前位置回退5字节
file:seek("end")      -- 移动到文件末尾

获取文件大小

local size = file:seek("end")
file:seek("set")  -- 重置位置

6. 二进制文件操作

读取二进制数据

local binfile = assert(io.open("data.bin", "rb"))
local data = binfile:read(4)  -- 读取4字节
binfile:close()

写入二进制数据

local out = assert(io.open("out.bin", "wb"))
out:write(string.char(0x48, 0x65, 0x6C, 0x6C, 0x6F))  -- 写入"Hello"
out:close()

7. 标准文件句柄

Lua 提供了三个标准文件句柄:

io.input()   -- 标准输入(默认为stdin)
io.output()  -- 标准输出(默认为stdout)
io.stderr    -- 标准错误输出

重定向标准输入输出

local temp = io.input()  -- 保存当前输入
io.input("newinput.txt") -- 重定向输入
-- 读取操作将来自newinput.txt
io.input():close()       -- 关闭文件
io.input(temp)           -- 恢复原输入

8. 文件系统操作(需要os库)

文件信息

local attr = io.popen("ls -l " .. filename)
print(attr:read("*a"))
attr:close()

文件存在检查

function fileExists(name)
    local f = io.open(name, "r")
    if f then
        f:close()
        return true
    end
    return false
end

9. 高级文件操作技巧

内存映射文件模拟

function map_file(path)
    local file = assert(io.open(path, "rb"))
    local data = file:read("*a")
    file:close()
    return {
        data = data,
        size = #data,
        readInt = function(self, offset)
            return string.unpack("<i4", self.data, offset)
        end
    }
end

local mapped = map_file("data.bin")
print(mapped:readInt(10))  -- 读取偏移10处的4字节整数

文件锁实现(简单版)

function acquireLock(lockfile)
    while true do
        local lock = io.open(lockfile, "wx")
        if lock then
            return lock
        end
        os.execute("sleep 0.1")  -- 等待100ms
    end
end

function releaseLock(lock)
    lock:close()
end

-- 使用
local lock = acquireLock("/tmp/mylock")
-- 临界区操作
releaseLock(lock)

10. 性能优化建议

  1. 大文件处理:避免一次性读取大文件,应逐块处理

    while true do
        local block = file:read(8192)  -- 8KB块
        if not block then break end
        -- 处理块数据
    end
    
  2. 批量写入:减少IO操作次数

    local buffer = {}
    -- 收集写入内容
    table.insert(buffer, "数据1\n")
    table.insert(buffer, "数据2\n")
    -- 一次性写入
    file:write(table.concat(buffer))
    
  3. 使用合适的缓冲区大小:通常8KB-64KB性能较好

Lua 的文件 I/O 功能虽然简单,但配合字符串处理能力可以完成各种复杂的文件操作任务。对于更高级的文件系统操作,可以考虑使用 lfs (LuaFileSystem) 等第三方库。