保存表有几种方法,选用那种方法取决于对具体表结构的假设,但没有一种算法适用于所有的情况。对于简单的表来说,不仅可以使用更简单的算法,而且输出也会更简洁和清晰。
先看一个简单的想法:
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 io.write(" ", k, " = ") serialize(v) io.write(",\n") end io.write("}\n") else error("cannot serialize a " .. type(o)) end end
尽管这个函数很简单,但它却可以合理地满足需求。只要表结构是一棵树(即没有共享的字表和环),那么该函数甚至能够处理嵌套的表(即表中还有其他的表)。
上例中的函数假设了表中的所有键都是合法的标识符,如果一个表的键是数字或者不是合法的 Lua
标志符,那么就会有问题。解决该问题的一种简单方式是像下列代码一样处理每个键:
io.write(string.format(" [%s] = ", serialize(k)))
经过这样的修改,我们提高了该函数的健壮性,但却牺牲了结果文件的美观性。考虑如下调用:
serialize{a = 12, b = 'Lua', key = 'another "one"'}
第一版的函数 serialize
会输出:
{ a = 12, b = "Lua", key = "another \"one\"", }
与之对比,第二版的函数 serialize
则会输出:
{ ["a"] = 12, ["b"] = "Lua", ["key"] = "another \"one\"", }
提示
代码运行失败。。。
通过测试每个键是否需要方括号,可以在健壮性和美观性之间得到平衡。