一、数据文件

如果在 Lua 程序中能够需求用文件保存数据,而且后续运用 Lua 进行读取运用,则能够考虑将数据依照一定的格局保存,然后用 dofile 函数进行加载,这样能够让数据很方便的进行读取。

我们能够将数据依照 EntryName{} 或许 EntryName({}) 方法存储,这样一旦运用 dofile 加载,则会让数据文件解析为调用了 EntryName 函数,而且将 {} 内的内容解析为一个 table 作为一个参数传入函数。(在只要一个参数时,函数的调用携带参数是能够省掉括号的)

dofile 的详细运用鄙人一篇文章进行共享

接下来经过完整的例子体会一下吧

数据文件的内容

Entry{
    "江澎涌",
    "28",
    1994,
}
Entry{
    "小朋友",
    "20",
    2000
}

加载代码

local count = 0
function Entry()
    count = count + 1
end
-- 内部会调用 entry
dofile("/Users/jiangpengyong/Desktop/code/Lua/lua_study_2022/9 数据文件和序列化/data.txt")
print("number of entries: " .. count)       --> number of entries: 2

数据文件中会调用 Entry 函数,并将 {} 作为入参,所以能做的工作很多,并不止局限于计算个数,也能够将数据收集,例如下面的代码,当然也能够做一些加工。

local authors = {}
function Entry(author)
    table.insert(authors, author)
end
-- 内部会调用 entry
dofile("/Users/jiangpengyong/Desktop/code/Lua/lua_study_2022/9 数据文件和序列化/data.txt")
for key, author in pairs(authors) do
    print("key: ", key)
    for key, value in pairs(author) do
        print(key, "--", value)
    end
end
--> key: 	1
--> 1	--	江澎涌
--> 2	--	28
--> 3	--	1994
--> key: 	2
--> 1	--	小朋友
--> 2	--	20
--> 3	--	2000

二、序列化为数据文件

在编写一个序列化工具中,需求注意的一些小点:

  1. string 类型要注意一些需求转义的字符,能够考虑运用 string.format("%q", content),会将特殊字符转义,而且能够很好的兼容数值、nil、boolean 类型。值得一提的是浮点数的数值会运用十六进制浮点数记录,确保他的精度。
  2. 如果不考虑运用 string.format("%q", content) ,则需求运用 "" 表明字符串,则需求注意代码注入,能够考虑 [==[ .. ]==] ( = 能够是恣意多个,具体能够翻阅字符串一章) 方法来表明长字符串。仅仅要兼容好字符串内容也存在长字符串的格局,能够运用比内容多一个 = 的方法。
  3. 保存可能存在相互嵌套,但 Lua 的 table 构造器不支持嵌套,所以需求进行处理

2-1、不嵌套保存

关于不保存嵌套的 table ,能够运用以下代码,保存后的数据文件清晰明了

function serialize(o)
    local t = type(o)
    if t == "number" or t == "string" or t == "boolean" or t == "nil" then
        io.write(string.format("%q", o))
    elseif t == "table" then
        io.write("{\n")
        for k, v in pairs(o) do
            --- 第一种:这种做法能让 key = value 的形式比较直观,但带来的缺陷是一些关键字不能兼容
            --io.write("  ", k, " = ")
            --- 第二种:可读性比较差,以 ["key"] = value 形式保存,可是能够兼容一切关键字
            io.write(" [")
            serialize(k)
            io.write("] = ")
            serialize(v)
            io.write(",\n")
        end
        io.write("}\n")
    else
        error(string.format("cannot serialize a %s", type(o)))
    end
end
print(serialize({ a = 12, b = 'Lua', key = 'another "one"' }))
--> {
-->  ["b"] = "Lua",
-->  ["a"] = 12,
-->  ["key"] = "another \"one\"",
--> }

2-2、保存嵌套

local function basicSerialize(o)
    -- 关于 Lua 5.3.3 开端, %q 能够正常的显现字符串、 nil 、 数值(浮点数会运用十六进制进行确保精度)和 boolean 类型
    return string.format("%q", o)
end
function save(name, value, saved)
    saved = saved or {}
    io.write(name, " = ")
    if type(value) == "number"
            or type(value) == "string"
            or type(value) == "boolean"
            or type(value) == "nil"
    then
        io.write(basicSerialize(value), "\n")
    elseif type(value) == "table" then
        if saved[value] then
            io.write(saved[value], "\n")
        else
            saved[value] = name
            io.write("{}\n")
            for k, v in pairs(value) do
                k = basicSerialize(k)
                local fname = string.format("%s[%s]", name, k)
                save(fname, v, saved)
            end
        end
    else
        error("can't save a " .. type(value))
    end
end
local table = {}
jiang = {}
xiao = {}
jiang[1] = xiao
xiao[1] = jiang
save("a", jiang, table)
--> a = {}
--> a[1] = {}
--> a[1][1] = a

三、写在最后

Lua 项目地址:Github传送门 (如果对你有所协助或喜爱的话,赏个star吧,码字不易,请多多支持)

如果觉得本篇博文对你有所启示或是解决了困惑,点个赞或重视我呀

公众号查找 “江澎涌”,更多优质文章会第一时间共享与你。

Lua 数据文件和序列化