Skip to content

Lua文件和IO操作

概述

文件和输入输出(I/O)操作是程序与外部世界交互的重要方式。Lua提供了完整的文件操作API,支持文本文件和二进制文件的读写,以及标准输入输出操作。

1. 文件操作基础

1.1 打开和关闭文件

lua
-- 基本文件打开
local file = io.open("test.txt", "r")  -- 只读模式
if file then
    print("文件打开成功")
    file:close()
else
    print("文件打开失败")
end

-- 文件打开模式
local modes = {
    ["r"] = "只读模式(默认)",
    ["w"] = "只写模式,清空文件内容",
    ["a"] = "追加模式,在文件末尾写入",
    ["r+"] = "读写模式,文件必须存在",
    ["w+"] = "读写模式,清空文件内容",
    ["a+"] = "读写模式,在文件末尾写入",
    ["rb"] = "二进制只读模式",
    ["wb"] = "二进制只写模式",
    ["ab"] = "二进制追加模式"
}

for mode, description in pairs(modes) do
    print(mode .. ": " .. description)
end

-- 安全的文件打开
local function safe_open_file(filename, mode)
    local file, err = io.open(filename, mode)
    if not file then
        error("无法打开文件 " .. filename .. ": " .. (err or "未知错误"))
    end
    return file
end

-- 使用示例
local success, file_or_error = pcall(safe_open_file, "example.txt", "w")
if success then
    file_or_error:write("Hello, World!")
    file_or_error:close()
    print("文件写入成功")
else
    print("错误:", file_or_error)
end

1.2 文件读取操作

lua
-- 创建测试文件
local function create_test_file()
    local file = io.open("test_data.txt", "w")
    file:write("第一行内容\n")
    file:write("第二行内容\n")
    file:write("第三行内容\n")
    file:write("123 456 789\n")
    file:write("最后一行")
    file:close()
end

create_test_file()

-- 不同的读取方式
local function demonstrate_read_methods()
    local file = io.open("test_data.txt", "r")
    if not file then return end
    
    print("=== 读取方法演示 ===")
    
    -- 1. 读取整个文件
    file:seek("set", 0)  -- 回到文件开头
    local all_content = file:read("*a")
    print("整个文件内容:")
    print(all_content)
    print("文件大小:", #all_content, "字节")
    
    -- 2. 逐行读取
    print("\n逐行读取:")
    file:seek("set", 0)  -- 回到文件开头
    local line_number = 1
    for line in file:lines() do
        print(string.format("第%d行: %s", line_number, line))
        line_number = line_number + 1
    end
    
    -- 3. 读取指定字节数
    print("\n读取指定字节数:")
    file:seek("set", 0)  -- 回到文件开头
    local chunk = file:read(10)  -- 读取前10个字节
    print("前10个字节:", chunk)
    
    -- 4. 读取数字
    file:seek("set", 0)  -- 回到文件开头
    -- 跳过前三行
    file:read("*l")
    file:read("*l")
    file:read("*l")
    
    local num1 = file:read("*n")  -- 读取数字
    local num2 = file:read("*n")
    local num3 = file:read("*n")
    print("读取的数字:", num1, num2, num3)
    
    file:close()
end

demonstrate_read_methods()

-- 高级读取示例
local function advanced_file_reading()
    local file = io.open("test_data.txt", "r")
    if not file then return end
    
    print("\n=== 高级读取示例 ===")
    
    -- 读取文件的前N行
    local function read_first_n_lines(file, n)
        local lines = {}
        file:seek("set", 0)
        for i = 1, n do
            local line = file:read("*l")
            if not line then break end
            lines[i] = line
        end
        return lines
    end
    
    local first_3_lines = read_first_n_lines(file, 3)
    print("前3行:")
    for i, line in ipairs(first_3_lines) do
        print("  " .. i .. ": " .. line)
    end
    
    -- 读取文件的最后N行
    local function read_last_n_lines(file, n)
        local lines = {}
        file:seek("set", 0)
        
        -- 先读取所有行
        for line in file:lines() do
            table.insert(lines, line)
        end
        
        -- 返回最后n行
        local start_index = math.max(1, #lines - n + 1)
        local result = {}
        for i = start_index, #lines do
            table.insert(result, lines[i])
        end
        return result
    end
    
    local last_2_lines = read_last_n_lines(file, 2)
    print("最后2行:")
    for i, line in ipairs(last_2_lines) do
        print("  " .. i .. ": " .. line)
    end
    
    file:close()
end

advanced_file_reading()

1.3 文件写入操作

lua
-- 基本写入操作
local function basic_write_operations()
    print("=== 基本写入操作 ===")
    
    -- 1. 创建新文件并写入
    local file = io.open("output.txt", "w")
    file:write("Hello, Lua!\n")
    file:write("这是第二行\n")
    file:write(string.format("当前时间: %s\n", os.date()))
    file:close()
    print("创建文件 output.txt")
    
    -- 2. 追加内容
    file = io.open("output.txt", "a")
    file:write("这是追加的内容\n")
    file:write("追加的第二行\n")
    file:close()
    print("追加内容到 output.txt")
    
    -- 3. 格式化写入
    file = io.open("formatted_output.txt", "w")
    local data = {
        {name = "Alice", age = 30, score = 95.5},
        {name = "Bob", age = 25, score = 87.2},
        {name = "Charlie", age = 35, score = 92.8}
    }
    
    file:write("姓名\t\t年龄\t分数\n")
    file:write(string.rep("-", 30) .. "\n")
    
    for _, person in ipairs(data) do
        file:write(string.format("%-10s\t%d\t%.1f\n", 
            person.name, person.age, person.score))
    end
    file:close()
    print("创建格式化文件 formatted_output.txt")
end

basic_write_operations()

-- 安全写入函数
local function safe_write_file(filename, content, mode)
    mode = mode or "w"
    local file, err = io.open(filename, mode)
    
    if not file then
        return false, "无法打开文件: " .. (err or "未知错误")
    end
    
    local success, write_err = pcall(function()
        file:write(content)
    end)
    
    file:close()
    
    if success then
        return true, nil
    else
        return false, "写入失败: " .. write_err
    end
end

-- 批量写入
local function batch_write_example()
    print("\n=== 批量写入示例 ===")
    
    local lines = {}
    for i = 1, 1000 do
        lines[i] = string.format("这是第 %d 行数据", i)
    end
    
    local content = table.concat(lines, "\n")
    local success, err = safe_write_file("large_file.txt", content)
    
    if success then
        print("成功写入1000行数据")
    else
        print("写入失败:", err)
    end
end

batch_write_example()

2. 文件位置操作

2.1 文件指针操作

lua
-- 文件指针操作示例
local function file_pointer_operations()
    print("=== 文件指针操作 ===")
    
    -- 创建测试文件
    local file = io.open("pointer_test.txt", "w")
    file:write("0123456789ABCDEFGHIJ")
    file:close()
    
    -- 重新打开进行读取
    file = io.open("pointer_test.txt", "r")
    
    -- 获取当前位置
    local pos = file:seek()
    print("初始位置:", pos)  -- 0
    
    -- 读取5个字符
    local data = file:read(5)
    print("读取的数据:", data)  -- 01234
    
    -- 获取当前位置
    pos = file:seek()
    print("读取后位置:", pos)  -- 5
    
    -- 移动到文件开头
    file:seek("set", 0)
    pos = file:seek()
    print("移动到开头后位置:", pos)  -- 0
    
    -- 移动到文件末尾
    file:seek("end", 0)
    pos = file:seek()
    print("移动到末尾后位置:", pos)  -- 20
    
    -- 相对移动
    file:seek("cur", -5)  -- 向前移动5个位置
    pos = file:seek()
    print("相对移动后位置:", pos)  -- 15
    
    -- 读取当前位置的数据
    data = file:read(3)
    print("当前位置读取:", data)  -- FGH
    
    file:close()
end

file_pointer_operations()

-- 随机访问文件
local function random_access_example()
    print("\n=== 随机访问示例 ===")
    
    -- 创建索引文件
    local records = {
        {id = 1, name = "Alice", data = "数据1"},
        {id = 2, name = "Bob", data = "数据2"},
        {id = 3, name = "Charlie", data = "数据3"}
    }
    
    local file = io.open("records.txt", "w")
    local index = {}  -- 记录每条记录的位置
    
    for _, record in ipairs(records) do
        local pos = file:seek()  -- 记录当前位置
        local line = string.format("%d|%s|%s\n", record.id, record.name, record.data)
        file:write(line)
        index[record.id] = {position = pos, length = #line}
    end
    file:close()
    
    -- 随机读取记录
    file = io.open("records.txt", "r")
    
    local function read_record_by_id(id)
        local record_info = index[id]
        if not record_info then
            return nil, "记录不存在"
        end
        
        file:seek("set", record_info.position)
        local line = file:read("*l")
        
        -- 解析记录
        local parts = {}
        for part in string.gmatch(line, "([^|]+)") do
            table.insert(parts, part)
        end
        
        return {
            id = tonumber(parts[1]),
            name = parts[2],
            data = parts[3]
        }
    end
    
    -- 测试随机访问
    for _, id in ipairs({3, 1, 2}) do
        local record = read_record_by_id(id)
        if record then
            print(string.format("ID %d: %s - %s", record.id, record.name, record.data))
        end
    end
    
    file:close()
end

random_access_example()

3. 二进制文件操作

3.1 二进制读写

lua
-- 二进制文件操作
local function binary_file_operations()
    print("=== 二进制文件操作 ===")
    
    -- 写入二进制数据
    local function write_binary_data()
        local file = io.open("binary_data.bin", "wb")
        
        -- 写入不同类型的数据
        local data = {
            0x12, 0x34, 0x56, 0x78,  -- 字节
            0x1234,                   -- 16位整数
            0x12345678,               -- 32位整数
        }
        
        for _, value in ipairs(data) do
            -- 将数字转换为字节写入
            if value <= 0xFF then
                file:write(string.char(value))
            elseif value <= 0xFFFF then
                -- 小端序写入16位整数
                file:write(string.char(value & 0xFF))
                file:write(string.char((value >> 8) & 0xFF))
            else
                -- 小端序写入32位整数
                file:write(string.char(value & 0xFF))
                file:write(string.char((value >> 8) & 0xFF))
                file:write(string.char((value >> 16) & 0xFF))
                file:write(string.char((value >> 24) & 0xFF))
            end
        end
        
        file:close()
        print("二进制数据写入完成")
    end
    
    -- 读取二进制数据
    local function read_binary_data()
        local file = io.open("binary_data.bin", "rb")
        if not file then
            print("无法打开二进制文件")
            return
        end
        
        print("读取二进制数据:")
        
        -- 读取单个字节
        for i = 1, 4 do
            local byte = file:read(1)
            if byte then
                print(string.format("字节 %d: 0x%02X", i, string.byte(byte)))
            end
        end
        
        -- 读取16位整数(小端序)
        local low = string.byte(file:read(1))
        local high = string.byte(file:read(1))
        local int16 = low + (high << 8)
        print(string.format("16位整数: 0x%04X", int16))
        
        -- 读取32位整数(小端序)
        local bytes = {}
        for i = 1, 4 do
            bytes[i] = string.byte(file:read(1))
        end
        local int32 = bytes[1] + (bytes[2] << 8) + (bytes[3] << 16) + (bytes[4] << 24)
        print(string.format("32位整数: 0x%08X", int32))
        
        file:close()
    end
    
    write_binary_data()
    read_binary_data()
end

binary_file_operations()

-- 二进制文件工具函数
local BinaryFile = {}
BinaryFile.__index = BinaryFile

function BinaryFile.new(filename, mode)
    local file = io.open(filename, mode)
    if not file then
        error("无法打开文件: " .. filename)
    end
    
    return setmetatable({
        file = file,
        filename = filename
    }, BinaryFile)
end

function BinaryFile:write_uint8(value)
    self.file:write(string.char(value & 0xFF))
end

function BinaryFile:write_uint16_le(value)
    self.file:write(string.char(value & 0xFF))
    self.file:write(string.char((value >> 8) & 0xFF))
end

function BinaryFile:write_uint32_le(value)
    self.file:write(string.char(value & 0xFF))
    self.file:write(string.char((value >> 8) & 0xFF))
    self.file:write(string.char((value >> 16) & 0xFF))
    self.file:write(string.char((value >> 24) & 0xFF))
end

function BinaryFile:read_uint8()
    local byte = self.file:read(1)
    return byte and string.byte(byte) or nil
end

function BinaryFile:read_uint16_le()
    local low = self:read_uint8()
    local high = self:read_uint8()
    if low and high then
        return low + (high << 8)
    end
    return nil
end

function BinaryFile:read_uint32_le()
    local bytes = {}
    for i = 1, 4 do
        bytes[i] = self:read_uint8()
        if not bytes[i] then return nil end
    end
    return bytes[1] + (bytes[2] << 8) + (bytes[3] << 16) + (bytes[4] << 24)
end

function BinaryFile:close()
    self.file:close()
end

-- 使用二进制文件工具
local function test_binary_tools()
    print("\n=== 二进制工具测试 ===")
    
    -- 写入数据
    local writer = BinaryFile.new("test_binary.bin", "wb")
    writer:write_uint8(0x12)
    writer:write_uint16_le(0x3456)
    writer:write_uint32_le(0x789ABCDE)
    writer:close()
    
    -- 读取数据
    local reader = BinaryFile.new("test_binary.bin", "rb")
    local uint8 = reader:read_uint8()
    local uint16 = reader:read_uint16_le()
    local uint32 = reader:read_uint32_le()
    reader:close()
    
    print(string.format("读取结果: 0x%02X, 0x%04X, 0x%08X", uint8, uint16, uint32))
end

test_binary_tools()

4. 标准输入输出

4.1 标准IO操作

lua
-- 标准输入输出操作
local function standard_io_operations()
    print("=== 标准IO操作 ===")
    
    -- 标准输出
    io.write("这是使用io.write输出的文本\n")
    io.stdout:write("这是直接使用stdout输出的文本\n")
    
    -- 格式化输出
    io.write(string.format("格式化输出: %s, %d, %.2f\n", "测试", 42, 3.14159))
    
    -- 刷新输出缓冲区
    io.write("输出但不换行")
    io.flush()  -- 强制刷新
    io.write(" - 继续输出\n")
    
    -- 标准错误输出
    io.stderr:write("这是错误信息\n")
end

standard_io_operations()

-- 模拟交互式输入(实际使用时取消注释)
local function interactive_input_demo()
    print("\n=== 交互式输入演示 ===")
    
    --[[
    -- 读取一行输入
    io.write("请输入您的姓名: ")
    local name = io.read("*l")
    print("您好, " .. name .. "!")
    
    -- 读取数字
    io.write("请输入一个数字: ")
    local number = io.read("*n")
    if number then
        print("您输入的数字是: " .. number)
        print("它的平方是: " .. (number * number))
    else
        print("输入的不是有效数字")
    end
    
    -- 读取多个值
    io.write("请输入两个数字(用空格分隔): ")
    local a, b = io.read("*n", "*n")
    if a and b then
        print(string.format("%g + %g = %g", a, b, a + b))
    end
    --]]
    
    print("(交互式输入演示代码已注释,实际使用时请取消注释)")
end

interactive_input_demo()

-- 输入验证函数
local function get_valid_input(prompt, validator, error_message)
    while true do
        io.write(prompt)
        local input = io.read("*l")
        
        if validator(input) then
            return input
        else
            print(error_message or "输入无效,请重试")
        end
    end
end

-- 输入验证示例
local function input_validation_example()
    print("\n=== 输入验证示例 ===")
    
    -- 验证器函数
    local function is_valid_email(email)
        return string.match(email, "^[%w%.%-_]+@[%w%.%-_]+%.%w+$") ~= nil
    end
    
    local function is_valid_age(age_str)
        local age = tonumber(age_str)
        return age and age >= 0 and age <= 150
    end
    
    --[[
    -- 获取有效的邮箱地址
    local email = get_valid_input(
        "请输入邮箱地址: ",
        is_valid_email,
        "邮箱格式不正确,请重新输入"
    )
    
    -- 获取有效的年龄
    local age_str = get_valid_input(
        "请输入年龄 (0-150): ",
        is_valid_age,
        "年龄必须是0-150之间的数字"
    )
    
    print("验证通过!")
    print("邮箱: " .. email)
    print("年龄: " .. age_str)
    --]]
    
    print("(输入验证示例代码已注释,实际使用时请取消注释)")
end

input_validation_example()

5. 文件系统操作

5.1 文件和目录信息

lua
-- 文件系统操作
local function file_system_operations()
    print("=== 文件系统操作 ===")
    
    -- 检查文件是否存在
    local function file_exists(filename)
        local file = io.open(filename, "r")
        if file then
            file:close()
            return true
        end
        return false
    end
    
    -- 获取文件大小
    local function get_file_size(filename)
        local file = io.open(filename, "r")
        if not file then return nil end
        
        local size = file:seek("end")
        file:close()
        return size
    end
    
    -- 测试文件操作
    local test_files = {"test_data.txt", "output.txt", "nonexistent.txt"}
    
    for _, filename in ipairs(test_files) do
        if file_exists(filename) then
            local size = get_file_size(filename)
            print(string.format("%s: 存在, 大小 %d 字节", filename, size))
        else
            print(string.format("%s: 不存在", filename))
        end
    end
    
    -- 文件复制
    local function copy_file(source, destination)
        local src_file = io.open(source, "rb")
        if not src_file then
            return false, "无法打开源文件"
        end
        
        local dst_file = io.open(destination, "wb")
        if not dst_file then
            src_file:close()
            return false, "无法创建目标文件"
        end
        
        -- 分块复制
        local chunk_size = 4096
        while true do
            local chunk = src_file:read(chunk_size)
            if not chunk then break end
            dst_file:write(chunk)
        end
        
        src_file:close()
        dst_file:close()
        return true
    end
    
    -- 测试文件复制
    if file_exists("test_data.txt") then
        local success, err = copy_file("test_data.txt", "test_data_copy.txt")
        if success then
            print("文件复制成功: test_data.txt -> test_data_copy.txt")
        else
            print("文件复制失败:", err)
        end
    end
end

file_system_operations()

-- 目录操作(需要lfs库或使用os.execute)
local function directory_operations()
    print("\n=== 目录操作 ===")
    
    -- 创建目录
    local function create_directory(dirname)
        local success = os.execute("mkdir " .. dirname)
        return success == 0 or success == true
    end
    
    -- 删除文件
    local function delete_file(filename)
        return os.remove(filename)
    end
    
    -- 列出目录内容(Windows)
    local function list_directory_windows(dirname)
        local handle = io.popen("dir \"" .. dirname .. "\" /b")
        if not handle then return {} end
        
        local files = {}
        for line in handle:lines() do
            table.insert(files, line)
        end
        handle:close()
        return files
    end
    
    -- 列出目录内容(Unix/Linux)
    local function list_directory_unix(dirname)
        local handle = io.popen("ls \"" .. dirname .. "\"")
        if not handle then return {} end
        
        local files = {}
        for line in handle:lines() do
            table.insert(files, line)
        end
        handle:close()
        return files
    end
    
    -- 跨平台目录列表
    local function list_directory(dirname)
        if package.config:sub(1,1) == "\\" then
            return list_directory_windows(dirname)
        else
            return list_directory_unix(dirname)
        end
    end
    
    -- 测试目录操作
    print("当前目录内容:")
    local files = list_directory(".")
    for i, file in ipairs(files) do
        if i <= 10 then  -- 只显示前10个
            print("  " .. file)
        elseif i == 11 then
            print("  ...")
            break
        end
    end
end

directory_operations()

6. 高级文件操作

6.1 文件监控和处理

lua
-- 高级文件操作
local FileProcessor = {}
FileProcessor.__index = FileProcessor

function FileProcessor.new()
    return setmetatable({
        processors = {},
        filters = {}
    }, FileProcessor)
end

function FileProcessor:add_processor(name, processor_func)
    self.processors[name] = processor_func
end

function FileProcessor:add_filter(filter_func)
    table.insert(self.filters, filter_func)
end

function FileProcessor:process_file(filename)
    -- 检查文件是否通过所有过滤器
    for _, filter in ipairs(self.filters) do
        if not filter(filename) then
            return false, "文件被过滤器拒绝"
        end
    end
    
    local results = {}
    
    -- 应用所有处理器
    for name, processor in pairs(self.processors) do
        local success, result = pcall(processor, filename)
        if success then
            results[name] = result
        else
            results[name] = "处理失败: " .. result
        end
    end
    
    return true, results
end

-- 使用文件处理器
local function file_processor_example()
    print("\n=== 文件处理器示例 ===")
    
    local processor = FileProcessor.new()
    
    -- 添加过滤器
    processor:add_filter(function(filename)
        return string.match(filename, "%.txt$") ~= nil  -- 只处理.txt文件
    end)
    
    -- 添加处理器
    processor:add_processor("line_count", function(filename)
        local file = io.open(filename, "r")
        if not file then return "无法打开文件" end
        
        local count = 0
        for _ in file:lines() do
            count = count + 1
        end
        file:close()
        return count .. " 行"
    end)
    
    processor:add_processor("word_count", function(filename)
        local file = io.open(filename, "r")
        if not file then return "无法打开文件" end
        
        local content = file:read("*a")
        file:close()
        
        local word_count = 0
        for word in string.gmatch(content, "%S+") do
            word_count = word_count + 1
        end
        return word_count .. " 个单词"
    end)
    
    processor:add_processor("file_size", function(filename)
        local file = io.open(filename, "r")
        if not file then return "无法打开文件" end
        
        local size = file:seek("end")
        file:close()
        return size .. " 字节"
    end)
    
    -- 处理文件
    local test_files = {"test_data.txt", "output.txt", "binary_data.bin"}
    
    for _, filename in ipairs(test_files) do
        local success, results = processor:process_file(filename)
        
        if success then
            print(filename .. ":")
            for processor_name, result in pairs(results) do
                print("  " .. processor_name .. ": " .. result)
            end
        else
            print(filename .. ": " .. results)
        end
    end
end

file_processor_example()

-- 文件批处理
local function batch_file_processing()
    print("\n=== 批处理示例 ===")
    
    -- 批量创建测试文件
    local function create_test_files()
        local file_contents = {
            "这是第一个测试文件\n包含两行内容",
            "第二个文件\n有三行\n内容",
            "第三个文件只有一行",
            "最后一个文件\n有四行\n不同的\n内容"
        }
        
        for i, content in ipairs(file_contents) do
            local filename = string.format("batch_test_%d.txt", i)
            local file = io.open(filename, "w")
            file:write(content)
            file:close()
        end
        
        print("创建了4个测试文件")
    end
    
    -- 批量处理文件
    local function process_batch_files()
        local total_lines = 0
        local total_size = 0
        local file_count = 0
        
        for i = 1, 4 do
            local filename = string.format("batch_test_%d.txt", i)
            local file = io.open(filename, "r")
            
            if file then
                -- 统计行数
                local lines = 0
                for _ in file:lines() do
                    lines = lines + 1
                end
                
                -- 获取文件大小
                local size = file:seek("end")
                file:close()
                
                total_lines = total_lines + lines
                total_size = total_size + size
                file_count = file_count + 1
                
                print(string.format("%s: %d 行, %d 字节", filename, lines, size))
            end
        end
        
        print(string.format("总计: %d 个文件, %d 行, %d 字节", 
            file_count, total_lines, total_size))
    end
    
    create_test_files()
    process_batch_files()
    
    -- 清理测试文件
    for i = 1, 4 do
        local filename = string.format("batch_test_%d.txt", i)
        os.remove(filename)
    end
    print("清理测试文件完成")
end

batch_file_processing()

7. 性能优化和最佳实践

7.1 高效文件操作

lua
-- 性能优化示例
local function performance_optimization()
    print("=== 性能优化示例 ===")
    
    -- 创建大文件用于测试
    local function create_large_file(filename, lines)
        local file = io.open(filename, "w")
        for i = 1, lines do
            file:write(string.format("这是第 %d 行数据,包含一些测试内容\n", i))
        end
        file:close()
    end
    
    create_large_file("large_test.txt", 10000)
    
    -- 低效的逐行处理
    local function slow_line_processing(filename)
        local start_time = os.clock()
        local file = io.open(filename, "r")
        local line_count = 0
        
        for line in file:lines() do
            line_count = line_count + 1
            -- 模拟处理每一行
            string.upper(line)
        end
        
        file:close()
        local end_time = os.clock()
        return line_count, end_time - start_time
    end
    
    -- 高效的块处理
    local function fast_chunk_processing(filename)
        local start_time = os.clock()
        local file = io.open(filename, "r")
        local line_count = 0
        local chunk_size = 8192
        
        while true do
            local chunk = file:read(chunk_size)
            if not chunk then break end
            
            -- 统计换行符数量
            for _ in string.gmatch(chunk, "\n") do
                line_count = line_count + 1
            end
        end
        
        file:close()
        local end_time = os.clock()
        return line_count, end_time - start_time
    end
    
    -- 性能比较
    local slow_lines, slow_time = slow_line_processing("large_test.txt")
    local fast_lines, fast_time = fast_chunk_processing("large_test.txt")
    
    print(string.format("逐行处理: %d 行, %.4f 秒", slow_lines, slow_time))
    print(string.format("块处理: %d 行, %.4f 秒", fast_lines, fast_time))
    print(string.format("性能提升: %.2f 倍", slow_time / fast_time))
    
    -- 清理
    os.remove("large_test.txt")
end

performance_optimization()

-- 内存友好的大文件处理
local function memory_efficient_processing()
    print("\n=== 内存友好处理 ===")
    
    -- 创建超大文件
    local function create_huge_file(filename, size_mb)
        local file = io.open(filename, "w")
        local line = string.rep("a", 80) .. "\n"  -- 81字节的行
        local lines_per_mb = math.floor(1024 * 1024 / 81)
        
        for mb = 1, size_mb do
            for line_in_mb = 1, lines_per_mb do
                file:write(line)
            end
        end
        
        file:close()
    end
    
    -- 流式处理大文件
    local function stream_process_file(input_filename, output_filename, processor)
        local input_file = io.open(input_filename, "r")
        local output_file = io.open(output_filename, "w")
        
        if not input_file or not output_file then
            if input_file then input_file:close() end
            if output_file then output_file:close() end
            return false, "无法打开文件"
        end
        
        local chunk_size = 4096
        local processed_bytes = 0
        
        while true do
            local chunk = input_file:read(chunk_size)
            if not chunk then break end
            
            local processed_chunk = processor(chunk)
            output_file:write(processed_chunk)
            processed_bytes = processed_bytes + #chunk
            
            -- 定期报告进度
            if processed_bytes % (1024 * 1024) == 0 then
                print(string.format("已处理 %d MB", processed_bytes / (1024 * 1024)))
            end
        end
        
        input_file:close()
        output_file:close()
        return true, processed_bytes
    end
    
    -- 示例:将文件内容转换为大写
    local function uppercase_processor(chunk)
        return string.upper(chunk)
    end
    
    print("创建测试文件...")
    create_huge_file("huge_test.txt", 5)  -- 5MB文件
    
    print("开始流式处理...")
    local success, bytes = stream_process_file("huge_test.txt", "huge_upper.txt", uppercase_processor)
    
    if success then
        print(string.format("处理完成,共处理 %d 字节", bytes))
    else
        print("处理失败:", bytes)
    end
    
    -- 清理
    os.remove("huge_test.txt")
    os.remove("huge_upper.txt")
end

memory_efficient_processing()

7.2 错误处理和资源管理

lua
-- 安全的文件操作模式
local function safe_file_operations()
    print("\n=== 安全文件操作 ===")
    
    -- RAII风格的文件操作
    local function with_file(filename, mode, operation)
        local file, err = io.open(filename, mode)
        if not file then
            return nil, "无法打开文件: " .. (err or "未知错误")
        end
        
        local success, result = pcall(operation, file)
        file:close()
        
        if success then
            return result
        else
            return nil, "操作失败: " .. result
        end
    end
    
    -- 使用RAII模式
    local result, err = with_file("test_data.txt", "r", function(file)
        local lines = {}
        for line in file:lines() do
            table.insert(lines, line)
        end
        return lines
    end)
    
    if result then
        print("成功读取", #result, "行")
    else
        print("读取失败:", err)
    end
    
    -- 事务性文件操作
    local function atomic_file_write(filename, content)
        local temp_filename = filename .. ".tmp"
        
        -- 写入临时文件
        local success, err = with_file(temp_filename, "w", function(file)
            file:write(content)
            return true
        end)
        
        if not success then
            os.remove(temp_filename)
            return false, err
        end
        
        -- 原子性重命名(在大多数系统上)
        local rename_success = os.rename(temp_filename, filename)
        if not rename_success then
            os.remove(temp_filename)
            return false, "无法重命名临时文件"
        end
        
        return true
    end
    
    -- 测试原子写入
    local content = "这是原子写入的内容\n包含多行数据\n"
    local success, err = atomic_file_write("atomic_test.txt", content)
    
    if success then
        print("原子写入成功")
    else
        print("原子写入失败:", err)
    end
    
    -- 清理
    os.remove("atomic_test.txt")
end

safe_file_operations()

8. 实际应用示例

8.1 日志文件处理

lua
-- 日志文件处理系统
local LogProcessor = {}
LogProcessor.__index = LogProcessor

function LogProcessor.new()
    return setmetatable({
        patterns = {},
        statistics = {}
    }, LogProcessor)
end

function LogProcessor:add_pattern(name, pattern, extractor)
    self.patterns[name] = {
        pattern = pattern,
        extractor = extractor or function(match) return match end
    }
end

function LogProcessor:process_log_file(filename)
    local file = io.open(filename, "r")
    if not file then
        return false, "无法打开日志文件"
    end
    
    local line_number = 0
    local matches = {}
    
    for line in file:lines() do
        line_number = line_number + 1
        
        for pattern_name, pattern_info in pairs(self.patterns) do
            local match = string.match(line, pattern_info.pattern)
            if match then
                if not matches[pattern_name] then
                    matches[pattern_name] = {}
                end
                
                table.insert(matches[pattern_name], {
                    line_number = line_number,
                    data = pattern_info.extractor(match),
                    original_line = line
                })
            end
        end
    end
    
    file:close()
    return true, matches
end

-- 使用日志处理器
local function log_processing_example()
    print("\n=== 日志处理示例 ===")
    
    -- 创建示例日志文件
    local log_content = [[
2023-12-25 10:00:01 INFO User login: alice@example.com
2023-12-25 10:00:15 ERROR Database connection failed
2023-12-25 10:00:30 INFO User login: bob@example.com
2023-12-25 10:01:00 WARN High memory usage: 85%
2023-12-25 10:01:15 ERROR File not found: /path/to/file.txt
2023-12-25 10:01:30 INFO User logout: alice@example.com
]]
    
    local file = io.open("sample.log", "w")
    file:write(log_content)
    file:close()
    
    -- 配置日志处理器
    local processor = LogProcessor.new()
    
    processor:add_pattern("errors", "ERROR (.+)", function(error_msg)
        return {type = "error", message = error_msg}
    end)
    
    processor:add_pattern("user_actions", "User (%w+): ([%w@%.]+)", function(action, user)
        return {action = action, user = user}
    end)
    
    processor:add_pattern("warnings", "WARN (.+)", function(warning_msg)
        return {type = "warning", message = warning_msg}
    end)
    
    -- 处理日志
    local success, results = processor:process_log_file("sample.log")
    
    if success then
        print("日志分析结果:")
        for pattern_name, matches in pairs(results) do
            print(string.format("\n%s (%d 条):", pattern_name, #matches))
            for _, match in ipairs(matches) do
                print(string.format("  行 %d: %s", match.line_number, 
                    type(match.data) == "table" and 
                    table.concat({match.data.action or match.data.type, 
                                 match.data.user or match.data.message}, " - ") or 
                    tostring(match.data)))
            end
        end
    else
        print("日志处理失败:", results)
    end
    
    -- 清理
    os.remove("sample.log")
end

log_processing_example()

8.2 配置文件管理

lua
-- 配置文件管理器
local ConfigManager = {}
ConfigManager.__index = ConfigManager

function ConfigManager.new(filename)
    return setmetatable({
        filename = filename,
        config = {},
        comments = {}
    }, ConfigManager)
end

function ConfigManager:load()
    local file = io.open(self.filename, "r")
    if not file then
        return false, "配置文件不存在"
    end
    
    local line_number = 0
    local current_section = nil
    
    for line in file:lines() do
        line_number = line_number + 1
        
        -- 去除前后空白
        line = string.match(line, "^%s*(.-)%s*$")
        
        -- 跳过空行
        if line == "" then
            goto continue
        end
        
        -- 处理注释
        if string.match(line, "^#") then
            self.comments[line_number] = line
            goto continue
        end
        
        -- 处理节标题
        local section = string.match(line, "^%[(.+)%]$")
        if section then
            current_section = section
            if not self.config[section] then
                self.config[section] = {}
            end
            goto continue
        end
        
        -- 处理键值对
        local key, value = string.match(line, "^([^=]+)=(.*)$")
        if key and value then
            key = string.match(key, "^%s*(.-)%s*$")
            value = string.match(value, "^%s*(.-)%s*$")
            
            if current_section then
                self.config[current_section][key] = value
            else
                self.config[key] = value
            end
        end
        
        ::continue::
    end
    
    file:close()
    return true
end

function ConfigManager:save()
    local file = io.open(self.filename, "w")
    if not file then
        return false, "无法写入配置文件"
    end
    
    -- 写入全局配置
    for key, value in pairs(self.config) do
        if type(value) ~= "table" then
            file:write(string.format("%s=%s\n", key, value))
        end
    end
    
    -- 写入节配置
    for section, section_config in pairs(self.config) do
        if type(section_config) == "table" then
            file:write(string.format("\n[%s]\n", section))
            for key, value in pairs(section_config) do
                file:write(string.format("%s=%s\n", key, value))
            end
        end
    end
    
    file:close()
    return true
end

function ConfigManager:get(section, key)
    if key then
        return self.config[section] and self.config[section][key]
    else
        return self.config[section]
    end
end

function ConfigManager:set(section, key, value)
    if value then
        if not self.config[section] then
            self.config[section] = {}
        end
        self.config[section][key] = value
    else
        self.config[section] = key
    end
end

-- 使用配置管理器
local function config_manager_example()
    print("\n=== 配置管理示例 ===")
    
    -- 创建示例配置文件
    local config_content = [[
# 应用程序配置文件
app_name=MyApp
version=1.0.0

[database]
host=localhost
port=3306
username=admin
password=secret

[server]
port=8080
debug=true
]]
    
    local file = io.open("app.conf", "w")
    file:write(config_content)
    file:close()
    
    -- 加载配置
    local config = ConfigManager.new("app.conf")
    local success, err = config:load()
    
    if success then
        print("配置加载成功")
        
        -- 读取配置
        print("应用名称:", config:get("app_name"))
        print("数据库主机:", config:get("database", "host"))
        print("服务器端口:", config:get("server", "port"))
        
        -- 修改配置
        config:set("server", "port", "9090")
        config:set("server", "ssl", "true")
        
        -- 保存配置
        local save_success = config:save()
        if save_success then
            print("配置保存成功")
        else
            print("配置保存失败")
        end
    else
        print("配置加载失败:", err)
    end
    
    -- 清理
    os.remove("app.conf")
end

config_manager_example()

总结

Lua的文件和IO操作提供了完整的功能:

  1. 基本文件操作 - 打开、读取、写入、关闭文件
  2. 文件位置控制 - 支持随机访问和文件指针操作
  3. 二进制文件支持 - 处理二进制数据
  4. 标准IO - 与标准输入输出交互
  5. 文件系统操作 - 文件存在性检查、复制等
  6. 性能优化 - 块读取、流式处理等高效方法
  7. 错误处理 - 完善的错误处理和资源管理
  8. 实际应用 - 日志处理、配置管理等实用示例

掌握这些文件操作技术可以让你的Lua程序能够有效地处理各种文件和数据操作任务。

基于 MIT 许可发布