随之Lua的学习,从要记的各种语句到现在编写像样点的代码,真心地觉得我们在成长着。这段时间努力的学习Lua其实是被3D游戏所吸引。有人喜欢玩游戏,有人喜欢做游戏,而我竟是被那绚丽的画面吸引了。
好了,开始今天的学习了。
一、数据文件
首先是数据文件,借由table构造式来定义一种文件格式,在这种格式中,每条数据记录表示为一个Lua构造式。在上一篇中的entry{}的db.lua文件就是table作为一种文件格式的例子。entry是调用的函数,而函数的定义则是在entry = entry1。
现在又来例子了:
entry {"Donald E. Knuth", --entry是调用的函数
"Literate Programming",
"CSLI",
1992
}
entry {"Jon Bentley",
"More Programming Pearls",
"Addison-Wesley",
1990
}
保存为data.lua
我们调用这个文件:计算data.lua文件中调用了几次entry函数
local count = 0
function entry() count = count + 1 end
dofile("D:/Lua Program/data.lua") --我的data.lua存储的绝对路径,当然你也可以用相对路径了。
print("number of entries:" .. count)
这里的执行结果当然是2了
下面的例子则是打印data.lua文件中的人名
local authors = {}
function entry(b)
authors[b[1]] = true --b[1] 表示第一个参数,即人名
end
dofile("D:/Lua Program/data.lua")
for name in pairs(authors) do
print(name)
end
结果:
Donald E. Knuth
Jon Bentley
当然如果上面的数据文件改为:
entry {
author = "Donald E. Knuth",
title = "Literate Programming",
publisher = "CSLI",
year = 1992
}
那我们打印时,只用修改下面一句就可以了。这样做的好处就是人名在数据文件中不是第一个也能正确打印出来。function entry(b)
authors[b[1]] = true --改为authors[b.author] = true
end
二、串行化
串行化是将数据转换为一个字节流或字符流。这就是涉及如何写入到数据文件中的问题了。
serialize函数就是串行化操作。list是一个table。这个例子的用途是将list这个table串行化,以便可以更好的写入到数据文件中。
function serialize(o)
if type(o) == "number" then -- o为number型,直接写入
io.write(o)
elseif type(o) == "string" then -- o为string型,将o加上“”
io.write(string.format("%q",o)) --%q 用双引号来括住字符串
elseif type(o) == "table" then -- 如果为无环的table,加上{};有环的table下面例子处理
io.write("{\n")
for k,v in pairs(o) do
io.write(" "..k.."=")
serialize(v)
io.write(",\n")
end
io.write("}\n")
else
error("cannot serialize a "..type(o)) --不是这三种,我们不处理
end
end
list = {
title = "Tecgraf",
org = "Computer Graphics Technology Group, PUC-Rio",
url = "http://www.tecgraf.puc-rio.br",
contact = "Waldemar Celes",
description = "Tecgraf is the result of a partnership between of Rio de Janeiro",
list1 = {
"hellen",
"dfasf"
}
}
serialize(list) -- 将list串行化
执行结果:
{
contact="Waldemar Celes",
title="Tecgraf",
list1={
1="hellen",
2="dfasf",
}
,
url="http://www.tecgraf.puc-rio.br",
description="Tecgraf is the result of a partnership between of Rio de Janeiro",
org="Computer Graphics Technology Group, PUC-Rio",
}
看到这个结果,会发现以这样的格式写入到文件中,我们就可以对其进行操作,如同打印title等。
上面对于有环的table处理未涉及,下面就来处理。
什么是有环,例如:
a = {x=1,y=2,{3,4,5}}
a[2] = a -- 环
a["z"] = a[1] -- 共享子table
那么怎样处理呢?function basicSerialize(o) -- 串行化
if type(o) == "number" then
return tostring(o)
else --o不是数字就只是string型
return string.format("%q",o)
end
end
function save(name,value,saved)
saved = saved or {} -- 初始化saved
io.write(name,"=")
if type(value) == "number" or type(value) == "string" then
io.write(basicSerialize(value),"\n") -- 串行化number和string
elseif type(value) == "table" then
if saved[value] then -- 该value是否保存过
io.write(saved[value],"\n") --保存过,使用以前的名字
else
saved[value] = name --为下次使用保持名字
io.write("{}\n") --创建一个新的table
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("cannot save a "..type(value))
end
end<pre name="code" class="plain">a = {x=1,y=2,{3,4,5}}
a[2] = a
a["z"] = a[1]
save("a",a)
执行结果:>lua -e "io.stdout:setvbuf 'no'" "serialize.lua"
a={}
a[1]={}
a[1][1]=3
a[1][2]=4
a[1][3]=5
a[2]=a
a["y"]=2
a["x"]=1
a["z"]=a[1]
>Exit code: 0
本文要说明的是用Lua以一种文件格式来存储数据文件。