完整课程入口:996 全套课程体系 | Lua 学习路径 | 幂尔框架 mirs.cn
装备表、怪物表、商城价格表这类由策划在 Excel 维护的配置,导出 CSV 后由 Lua 解析成结构化 table,是配置管线的第一环。目标格式:按 id 索引的字典,字段名做 key,策划改表后无需改代码。
CSV 的两个陷阱:字段内含逗号(被引号包裹)、字段内含换行。简易逐字符状态机 40 行可写完:
local function parseCSV(text)
local rows, row, field, inQuote = {}, {}, "", false
local i, n = 1, #text
while i <= n do
local c = text:sub(i, i)
if inQuote then
if c == '"' then
if text:sub(i + 1, i + 1) == '"' then
field = field .. '"'; i = i + 1 -- 转义的引号
else
inQuote = false
end
else field = field .. c end
elseif c == '"' then inQuote = true
elseif c == "," then row[#row + 1] = field; field = ""
elseif c == "\n" then
row[#row + 1] = field; rows[#rows + 1] = row
row, field = {}, ""
else field = field .. c end
i = i + 1
end
if field ~= "" or #row > 0 then row[#row + 1] = field; rows[#rows + 1] = row end
return rows
end
第一行是表头,第二行起是数据,按表头拼成字典:
local rows = parseCSV(fileText)
local head = rows[1]
local items = {}
for r = 2, #rows do
local item = {}
for c = 1, #head do item[head[c]] = rows[r][c] end
items[tonumber(item.id) or item.id] = item
end
数字字段统一转码。 Excel 导出的数字是字符串,价格、概率字段必须 tonumber 收口,否则 price * 2 直接报错。空值归一。 CSV 空单元格解析出来是空串,按字段类型归一成 nil、0 或 false,避免下游判断 == "" 散落各处。加载耗时控制。 1 万行 x 20 列的表在 LuaJIT 下解析约 180ms,放进启动流程一次性执行;运行期只读解析结果,不做二次解析。
解析器必须能在入口处发现坏数据,否则一行错位的 CSV 会让下游业务全面报错。加载后按表头做三道校验:id 列必须存在且不重复(重复 id 打印行号并拒绝整表);数字列逐格 tonumber,转换失败收集到错误清单;必填列空值同样收集。三道校验全部通过才写入 items,任何一步失败保留上一版配置并打印报告:
local errs = {}
if seen[item.id] then
errs[#errs + 1] = ("行%d: id 重复 %s"):format(r, tostring(item.id))
end
if not tonumber(item.price) then
errs[#errs + 1] = ("行%d: price 非数字 %s"):format(r, tostring(item.price))
end
if #errs > 0 then
release_print("CSV 校验失败 " .. #errs .. " 条")
for _, e in ipairs(errs) do release_print(e) end
return false
end
错误报告带行号与字段名,策划改表后自己就能看懂哪里填错,运维不再充当人肉翻译。
CSV 解析器与配置中心对接后即可支持不重启更新:文件 MD5 变化触发重新解析,解析成功按引用原子替换,失败保留旧版。1 万行的表在 LuaJIT 下解析约 180ms,放进启动流程一次性执行;运行期只读解析结果,不做二次解析。配表流程定稿后,策划改 Excel → 导出 CSV → FTP 上传 → ConfigCenter:reload(),四步完成一次配置更新,全程不动代码。