<返回目录     Powered by claud/xia兄

第11课: 文件I/O

简单文件读取

文件I/O缓冲机制:

Lua的文件I/O使用缓冲机制来提高性能。默认情况下,文件使用行缓冲(对于文本文件)或全缓冲(对于二进制文件)。可以通过file:setvbuf(mode, size)来设置缓冲模式:'no'(无缓冲)、'line'(行缓冲)、'full'(全缓冲)。缓冲机制可以显著减少系统调用的次数,提高I/O性能,但在需要实时数据时可能需要禁用缓冲。

-- 读取整个文件
local file = io.open("test.txt", "r")
if file then
    local content = file:read("*a")  -- 读取全部内容
    print(content)
    file:close()
else
    print("文件打开失败")
end

-- 简化写法
local content = io.open("test.txt", "r"):read("*a")
io.close()

-- 使用io.input
io.input("test.txt")
local content = io.read("*a")
io.close()

-- 设置缓冲模式
local file = io.open("test.txt", "w")
file:setvbuf("no")  -- 无缓冲,实时写入
file:write("实时数据")
file:close()

-- 全缓冲模式(默认)
local file = io.open("test.txt", "w")
file:setvbuf("full", 8192)  -- 8KB缓冲区
file:write("数据")
file:flush()  -- 手动刷新缓冲区
file:close()

文件打开模式

-- 打开模式:
-- "r"  只读模式(默认)
-- "w"  写入模式(覆盖)
-- "a"  追加模式
-- "r+" 读写模式(文件必须存在)
-- "w+" 读写模式(覆盖或创建)
-- "a+" 读写模式(追加)
-- "b"  二进制模式(如"rb", "wb")

-- 写入文件
local file = io.open("output.txt", "w")
if file then
    file:write("Hello Lua\n")
    file:write("第二行\n")
    file:close()
end

-- 追加内容
local file = io.open("output.txt", "a")
if file then
    file:write("追加的内容\n")
    file:close()
end

读取文件的不同方式

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

-- "*a" 或 "*all" - 读取整个文件
local all = file:read("*a")

-- "*l" 或 "*line" - 读取一行(不含换行符)
file:seek("set", 0)  -- 回到文件开头
local line = file:read("*l")

-- "*L" - 读取一行(含换行符)
local lineWithNewline = file:read("*L")

-- "*n" - 读取一个数字
local number = file:read("*n")

-- 数字 - 读取指定字节数
file:seek("set", 0)
local bytes = file:read(10)

file:close()

-- 逐行读取
local file = io.open("test.txt", "r")
for line in file:lines() do
    print(line)
end
file:close()

写入文件

-- 基本写入
local file = io.open("data.txt", "w")
file:write("第一行\n")
file:write("第二行\n")
file:close()

-- 写入多个值
local file = io.open("numbers.txt", "w")
for i = 1, 10 do
    file:write(i, " ")
end
file:close()

-- 格式化写入
local file = io.open("formatted.txt", "w")
local name = "张三"
local age = 25
file:write(string.format("姓名: %s, 年龄: %d\n", name, age))
file:close()

-- 使用io.output
io.output("output.txt")
io.write("使用io.output写入\n")
io.close()

文件定位

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

-- file:seek([whence, [offset]])
-- whence: "set"(从头), "cur"(当前), "end"(从尾)

-- 获取当前位置
local pos = file:seek()
print("当前位置:", pos)

-- 移到文件开头
file:seek("set", 0)

-- 移到文件末尾
file:seek("end", 0)

-- 获取文件大小
local size = file:seek("end")
print("文件大小:", size, "字节")

-- 回到开头
file:seek("set", 0)

-- 相对移动
file:seek("cur", 10)  -- 向前移动10字节

file:close()

错误处理

-- 使用assert
local file = assert(io.open("test.txt", "r"), "文件打开失败")
local content = file:read("*a")
file:close()

-- 手动检查
local file, err = io.open("nonexistent.txt", "r")
if not file then
    print("错误:", err)
else
    local content = file:read("*a")
    file:close()
end

-- 使用pcall保护
local success, result = pcall(function()
    local file = io.open("test.txt", "r")
    local content = file:read("*a")
    file:close()
    return content
end)

if success then
    print("读取成功:", result)
else
    print("读取失败:", result)
end

二进制文件操作

-- 读取二进制文件
local file = io.open("image.png", "rb")
if file then
    local data = file:read("*a")
    print("文件大小:", #data, "字节")
    file:close()
end

-- 写入二进制文件
local file = io.open("output.bin", "wb")
if file then
    -- 写入字节
    file:write(string.char(0xFF, 0xFE, 0xFD))
    file:close()
end

-- 复制二进制文件
function copyFile(source, dest)
    local input = io.open(source, "rb")
    local output = io.open(dest, "wb")

    if input and output then
        local data = input:read("*a")
        output:write(data)
        input:close()
        output:close()
        return true
    end
    return false
end

copyFile("source.bin", "dest.bin")

目录操作(需要lfs库)

-- 安装: luarocks install luafilesystem
local lfs = require("lfs")

-- 获取当前目录
print("当前目录:", lfs.currentdir())

-- 切换目录
lfs.chdir("/tmp")

-- 创建目录
lfs.mkdir("newdir")

-- 删除目录
lfs.rmdir("newdir")

-- 遍历目录
for file in lfs.dir(".") do
    if file ~= "." and file ~= ".." then
        local attr = lfs.attributes(file)
        print(file, attr.mode, attr.size)
    end
end

-- 获取文件属性
local attr = lfs.attributes("test.txt")
if attr then
    print("模式:", attr.mode)
    print("大小:", attr.size)
    print("修改时间:", os.date("%Y-%m-%d %H:%M:%S", attr.modification))
end

实用文件操作函数

-- 检查文件是否存在
function fileExists(filename)
    local file = io.open(filename, "r")
    if file then
        file:close()
        return true
    end
    return false
end

-- 读取文件所有行
function readLines(filename)
    local lines = {}
    local file = io.open(filename, "r")
    if file then
        for line in file:lines() do
            table.insert(lines, line)
        end
        file:close()
    end
    return lines
end

-- 写入文件所有行
function writeLines(filename, lines)
    local file = io.open(filename, "w")
    if file then
        for _, line in ipairs(lines) do
            file:write(line, "\n")
        end
        file:close()
        return true
    end
    return false
end

-- 追加到文件
function appendToFile(filename, text)
    local file = io.open(filename, "a")
    if file then
        file:write(text, "\n")
        file:close()
        return true
    end
    return false
end

-- 获取文件大小
function getFileSize(filename)
    local file = io.open(filename, "r")
    if file then
        local size = file:seek("end")
        file:close()
        return size
    end
    return nil
end

CSV文件处理

-- 读取CSV文件
function readCSV(filename)
    local data = {}
    local file = io.open(filename, "r")
    if file then
        for line in file:lines() do
            local row = {}
            for value in string.gmatch(line, "([^,]+)") do
                table.insert(row, value)
            end
            table.insert(data, row)
        end
        file:close()
    end
    return data
end

-- 写入CSV文件
function writeCSV(filename, data)
    local file = io.open(filename, "w")
    if file then
        for _, row in ipairs(data) do
            file:write(table.concat(row, ","), "\n")
        end
        file:close()
        return true
    end
    return false
end

-- 使用示例
local data = {
    {"姓名", "年龄", "城市"},
    {"张三", "25", "北京"},
    {"李四", "30", "上海"}
}
writeCSV("data.csv", data)

local loaded = readCSV("data.csv")
for _, row in ipairs(loaded) do
    print(table.concat(row, " | "))
end

临时文件

-- 创建临时文件
local tmpfile = io.tmpfile()
tmpfile:write("临时数据\n")
tmpfile:seek("set", 0)
local content = tmpfile:read("*a")
print(content)
tmpfile:close()  -- 关闭时自动删除

-- 使用os.tmpname获取临时文件名
local tmpname = os.tmpname()
print("临时文件名:", tmpname)

local file = io.open(tmpname, "w")
file:write("临时内容")
file:close()

-- 使用完后删除
os.remove(tmpname)
重要提示:
练习题:
  1. 编写程序统计文本文件的行数、单词数和字符数
  2. 实现文件复制功能,支持进度显示
  3. 编写程序读取日志文件,提取错误信息
  4. 实现简单的配置文件读写功能