0Pricing
Lua Academy · 课时

读取文件内容

使用 file:read() 方法读取行、字节和完整内容。

读取文件内容 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。

读取整个文件

使用 f:read("a")(或 "*a")将整个文件读入一个字符串。这种方式简单易用,适合小型到中型文件。对于超大型文件,请分块读取或逐行读取,以避免内存问题。

local f = io.open("config.txt", "r")
if f then
  local content = f:read("a")
  f:close()
  print("Size:", #content, "bytes")
  print(content)
end

逐行读取

f:read("l") 读取下一行,并去除换行符。在 EOF 处返回 nil。使用 while 循环处理每一行。f:lines() 是完成相同操作的惯用简写形式。

local f = io.open("data.txt", "r")
if f then
  local line = f:read("l")
  while line ~= nil do
    print(line)
    line = f:read("l")
  end
  f:close()
end

-- Equivalent with for loop:
-- for line in io.lines("data.txt") do print(line) end

读取固定数量的字节

向 f:read(n) 传入数字,可以读取恰好 n 个字节。它返回一个最多包含 n 个字节的字符串(如果到达 EOF,返回的字节数可能更少),在 EOF 处返回 nil。这适用于二进制协议或结构化文件格式。

local f = io.open("binary.dat", "rb")
if f then
  -- Read 4-byte header
  local header = f:read(4)
  if header then
    print("Header bytes:", #header)
    for i = 1, #header do
      io.write(string.format("%02X ", header:byte(i)))
    end
    print()
  end
  f:close()
end

读取数字

f:read("n") 会跳过空白字符,从文件中读取下一个数字。如果下一个标记不是数字,则返回 Lua 数字或 nil。这对于读取结构化数值数据文件很有用。

-- File contains: "10 20 30.5 40"
local f = io.open("nums.txt", "r")
if f then
  local total = 0
  local n = f:read("n")
  while n do
    total = total + n
    n = f:read("n")
  end
  f:close()
  print("Sum:", total)
end

在文件中定位

f:seek(whence, offset) 移动文件位置。whence 可以是 "set"(从开头开始)、"cur"(从当前位置开始)或 "end"(从末尾开始)。该函数返回新的绝对位置。您可以使用它重新读取文件或跳转到文件中的其他位置。

local f = io.open("test.txt", "r")
if f then
  -- Jump to end, get file size
  local size = f:seek("end")
  print("File size:", size, "bytes")
  
  -- Seek back to start
  f:seek("set", 0)
  local first_line = f:read("l")
  print("First line:", first_line)
  f:close()
end

读取 CSV 文件

逐行解析 CSV 数据:读取每一行,然后使用 string.gmatch 按逗号拆分。在生产环境中,请处理带引号的字段以及引号内的逗号;对于简单数据,基本拆分即可。

local function parseCSV(path)
  local rows = {}
  for line in io.lines(path) do
    local row = {}
    for field in string.gmatch(line, "([^,]+)") do
      row[#row+1] = field
    end
    rows[#rows+1] = row
  end
  return rows
end

-- Example: "Alice,30,Engineer"
-- => {{"Alice","30","Engineer"}}

读取配置文件

一种简单的键值配置格式是 key=value:逐行读取,跳过注释和空行,然后使用 string.match 解析键值对。

local function loadConfig(path)
  local cfg = {}
  for line in io.lines(path) do
    -- Skip comments and blank lines
    if not line:match("^%s*#") and line:match("%S") then
      local k, v = line:match("^%s*(%w+)%s*=%s*(.-)%s*$")
      if k then cfg[k] = v end
    end
  end
  return cfg
end

local config = loadConfig("app.conf")
print(config.host, config.port)

分块读取

对于大型文件,请按固定大小分块读取,以避免将所有内容加载到内存中。每个数据块到达后立即处理。对于大于可用 RAM 的文件,这是必不可少的。

local function processLarge(path, chunkSize)
  chunkSize = chunkSize or 4096
  local f, err = io.open(path, "rb")
  if not f then return nil, err end
  local totalBytes = 0
  local chunk = f:read(chunkSize)
  while chunk do
    totalBytes = totalBytes + #chunk
    -- process chunk here
    chunk = f:read(chunkSize)
  end
  f:close()
  return totalBytes
end

读取每行中的多个值

当每行包含多个以空格或制表符分隔的值时,请使用 string.match 或 string.gmatch 提取这些值。这种模式适用于简单的结构化文本文件。

-- File: "Alice 95 A\nBob 87 B"
local results = {}
for line in io.lines("grades.txt") do
  local name, score, grade = line:match("(%S+)%s+(%d+)%s+(%S+)")
  if name then
    results[#results+1] = {
      name=name,
      score=tonumber(score),
      grade=grade
    }
  end
end

for _, r in ipairs(results) do
  print(r.name, r.score, r.grade)
end

io.lines 简写

io.lines(filename) 打开文件并返回行迭代器,完成后关闭文件。这是逐行读取文件且无需显式管理句柄的最简洁方式。

-- Count non-empty lines
local count = 0
for line in io.lines("data.txt") do
  if line:match("%S") then
    count = count + 1
  end
end
print("Non-empty lines:", count)

-- Collect all lines into a table
local lines = {}
for line in io.lines("data.txt") do
  lines[#lines+1] = line
end
print("Total lines:", #lines)

快速检查

当文件指针已经位于 EOF 时,f:read("a") 会返回什么?

回顾:读取文件

总结:

  • f:read("a") —— 将整个文件作为字符串读取
  • f:read("l") —— 读取一行,不包含换行符
  • f:read(n) —— 读取恰好 n 个字节
  • f:read("n") —— 读取下一个数字
  • io.lines(path) —— 行迭代器,自动关闭文件
  • f:seek() —— 跳转到指定位置

常见问题解答

「读取文件内容」课时是免费的吗?

是的 — 「读取文件内容」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。

「读取文件内容」这节课中我会学到什么?

使用 file:read() 方法读取行、字节和完整内容。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Lua Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「读取文件内容」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Lua Academy 课中编写并运行代码吗?

能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 io.open 打开文件
  2. 读取文件内容
  3. 写入和追加文件内容
  4. 关闭文件和错误处理
← 返回 Lua Academy