脚本专栏 
首页 > 脚本专栏 > 浏览文章

Lua教程(八):数据持久化

(编辑:jimmy 日期: 2024/12/24 浏览:3 次 )

1. 数据文件:

    我们可以利用Lua中table的构造式来定义一种文件格式,即文件中的数据是table构造并初始化的代码,这种方式对于Lua程序而言是非常方便和清晰的,如:
 复制代码 代码如下:
    Entry { "Stephen Liu", "Male", "Programmer", "BS" }
    Entry { "Jerry Tian", "Male", "Programmer", "BS" }
 
    需要注意的是,Entry{<code>}等价于Entry({<code>}),对于上面的数据条目,如果我们能够定义一个合适的Entry函数,就可以让这些数据成为我们Lua代码的一部分了。见如下代码及其注释:
复制代码 代码如下:
local count = 0
--这里预先定义了Entry函数,以便在执行dofile中的数据代码时,可以找到匹配的该函数。
function Entry() count = count + 1 end
dofile("d:/lua_data.conf")
print("number of entries: " .. count)

--输出结果为:
--number of entries: 2

相比于上面数据文件的格式,我们还可以定义一种更为清晰的“自描述的数据”格式,其中每项数据都伴随一个表示其含义的简短描述。采用这样的格式,即便今后数据项发生了变化,我们仍然可以在改动极小的情况下保持向后的兼容性。见如下数据格式和相关的代码:
复制代码 代码如下:
    Entry { name = "Stephen Liu", gender = "Male", job = "Programmer", education = "BS" }
    Entry { name = "Jerry Tian", gender = "Male", job = "Programmer", education = "BS" }

复制代码 代码如下:
local personInfo = {}
function Entry(b)
    --这里将table对象b的name字段值作为personInfo的key信息。
    if b.name then
        personInfo[b.name] = true
    end
end

dofile("d:/lua_data.conf")
for name in pairs(personInfo) do
    print(name)
end

--输出结果为:
--Jerry Tian
--Stephen Liu

可以看出这些代码片段都采用了事件驱动的做法。Entry函数作为一个回调函数,在执行dofile时为数据文件中的每个条目所调用。

    Lua不仅运行速度快,而且编译速度也快。这主要是因为Lua在设计之初就将数据描述作为Lua的主要应用之一所致。
    
    2. 序列化:

    相信有Java或C#开发经验的人对于这一术语并不陌生。就是将数据对象转换为字节流后在通过IO输出到文件或网络,读取的时候再将这些数据重新构造为与原始对象具有相同值的新对象。或者我们也可以将一段可执行的Lua代码作为序列化后的数据格式。比如:varname = <expr>,这里的<expr>表示计算变量varname的表达式。下面的示例代码用于序列化无环的table:
 复制代码 代码如下:
 function serialize(o)
    if type(o) == "number" then
        io.write(o)
    elseif type(o) == "string" then
        --string.format函数的"%q"参数可以转义字符串中的元字符。
        io.write(string.format("%q",o))
    elseif type(o) == "table" then
        io.write("{\n")
        --迭代table中的各个元素,同时递归的写出各个字段的value。
        --由此可以看出,这个简单例子可以支持嵌套的table。
        for k,v in pairs(o) do
            --这样做是为了防止k中包含非法的Lua标识符。
            io.write(" ["); serialize(k); io.write("] = ")
            serialize(v)
            io.write(",\n")
        end
        io.write("}\n")
    else
        error("cannot serialize a " .. type(o))
    end
end
 

上一篇:Lua教程(十九):C调用Lua
下一篇:Lua教程(十七):C API简介
一句话新闻
一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?