第2章 - 文件 I/O 操作
嗨,朋友!我是长安。
这一章我们来看看 Lua 的文件读写操作。Java 的 IO 体系非常庞大(InputStream、OutputStream、Reader、Writer、BufferedReader……),而 Lua 的文件操作就简单多了。
🤔 Lua IO 模型
Lua 提供两种 IO 模型:
| 模型 | 说明 | 类似 Java |
|---|---|---|
| 简单模型 | 使用 io.xxx 全局操作 | System.in / System.out |
| 完整模型 | 使用文件句柄操作 | FileReader / FileWriter |
📖 读取文件
简单模型
-- 打开文件并读取全部内容
io.input("config.txt") -- 设置输入文件
local content = io.read("*a") -- 读取全部内容
print(content)
io.close()
完整模型(推荐)
-- 读取整个文件
local file = io.open("config.txt", "r")
if file then
local content = file:read("*a") -- 读取全部
print(content)
file:close()
else
print("文件打开失败!")
end
逐行读取
-- 方式一:使用 lines 迭代器
local file = io.open("data.txt", "r")
if file then
for line in file:lines() do
print(line)
end
file:close()
end
-- 方式二:使用 io.lines(更简洁)
for line in io.lines("data.txt") do
print(line)
end
Java 对比
// Java 逐行读取
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("文件打开失败!");
}
// Java 11+ 读取全部内容
String content = Files.readString(Path.of("config.txt"));
✍️ 写入文件
-- 写入文件(覆盖模式)
local file = io.open("output.txt", "w")
if file then
file:write("第一行\n")
file:write("第二行\n")
file:write("数字: " .. 42 .. "\n")
file:close()
print("写入成功!")
end
-- 追加模式
local file = io.open("log.txt", "a")
if file then
file:write(os.date() .. " - 日志信息\n")
file:close()
end
Java 对比
// Java 写入文件
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
writer.write("第一行\n");
writer.write("第二行\n");
writer.write("数字: " + 42 + "\n");
} catch (IOException e) {
e.printStackTrace();
}
// Java 追加模式
try (FileWriter writer = new FileWriter("log.txt", true)) {
writer.write(new Date() + " - 日志信息\n");
}
📋 文件打开模式
| 模式 | 说明 | Java 对比 |
|---|---|---|
"r" | 只读(默认) | new FileReader() |
"w" | 写入(覆盖) | new FileWriter() |
"a" | 追加 | new FileWriter(file, true) |
"r+" | 读写 | new RandomAccessFile("rw") |
"w+" | 读写(覆盖) | — |
"a+" | 读写(追加) | — |
📖 read 的参数
| 参数 | 说明 | 示例 |
|---|---|---|
"*a" | 读取全部内容 | file:read("*a") |
"*l" | 读取一行(默认) | file:read("*l") |
"*n" | 读取一个数字 | file:read("*n") |
| 数字 n | 读取 n 个字节 | file:read(1024) |
local file = io.open("data.txt", "r")
if file then
-- 读取第一行
local line1 = file:read("*l")
print("第一行:", line1)
-- 读取剩余全部
local rest = file:read("*a")
print("剩余:", rest)
file:close()
end
🔧 实用示例:读取配置文件
-- 读取 key=value 格式的配置文件
local function loadConfig(filename)
local config = {}
local file = io.open(filename, "r")
if not file then
print("配置文件不存在: " .. filename)
return config
end
for line in file:lines() do
-- 跳过注释和空行
if line:sub(1, 1) ~= "#" and line:match("%S") then
local key, value = line:match("^(%w+)%s*=%s*(.+)$")
if key then
config[key] = value
end
end
end
file:close()
return config
end
-- 使用
-- config.txt 内容:
-- # 这是注释
-- host = localhost
-- port = 8080
-- debug = true
local config = loadConfig("config.txt")
print(config.host) -- localhost
print(config.port) -- 8080
// Java 等价:使用 Properties
Properties props = new Properties();
props.load(new FileInputStream("config.properties"));
String host = props.getProperty("host");
🔧 实用示例:简单日志工具
-- logger.lua
local M = {}
local logFile = nil
function M.init(filename)
logFile = io.open(filename, "a")
end
function M.log(level, message)
if logFile then
local timestamp = os.date("%Y-%m-%d %H:%M:%S")
logFile:write(string.format("[%s] [%s] %s\n", timestamp, level, message))
logFile:flush() -- 立即写入磁盘
end
end
function M.info(message) M.log("INFO", message) end
function M.warn(message) M.log("WARN", message) end
function M.error(message) M.log("ERROR", message) end
function M.close()
if logFile then
logFile:close()
logFile = nil
end
end
return M
-- 使用日志工具
local logger = require("logger")
logger.init("app.log")
logger.info("应用启动")
logger.warn("配置项缺失,使用默认值")
logger.error("数据库连接失败")
logger.close()
📝 小结
- Lua 文件操作比 Java 简单得多,核心就是
io.open、read、write、close - 推荐使用完整模型(文件句柄),更灵活可控
- 一定记得
close(),否则数据可能丢失 - 用
file:lines()逐行读取最方便 - 写入后用
file:flush()确保数据写入磁盘
➡️ 下一步
文件操作搞定了!下一章来学习 错误处理,看看 Lua 怎么处理异常。
💪 练习题
- 写一个程序,读取文件内容并统计行数和字符数。
- 写一个程序,把一个文件的内容复制到另一个文件。
- 实现一个简单的 CSV 文件解析器。
- Lua 的
io.open返回什么?如何判断文件是否打开成功?
答案提示
- 用
file:lines()遍历计数行数,file:read("*a")+#content统计字符数 local input = io.open(src,"r") local output = io.open(dst,"w") output:write(input:read("*a"))- 用
string.gmatch(line, "([^,]+)")分割每行的逗号分隔值 - 成功返回文件句柄,失败返回
nil+ 错误信息。用if file then判断
