12.1 序列化

我们经常需要序列化一些数据,为了将数据转换为字节流或者字符流,这样我们就可以保存到文件或者通过网络发送出去。我们可以在Lua代码中描述序列化的数据,在这种方式下,我们运行读取程序即可从代码中构造出保存的值。

通常,我们使用这样的方式varname = <exp>来保存一个全局变量的值。varname部分比较容易理解,下面我们来看看如何写一个产生值的代码。对于一个数值来说:

function serialize (o)

    if type(o) == "number" then

       io.write(o)

    else ...

end

对于字符串值而言,原始的写法应该是:

if type(o) == "string" then

    io.write("'", o, "'")

然而,如果字符串包含特殊字符(比如引号或者换行符),产生的代码将不是有效的Lua程序。这时候你可能用下面方法解决特殊字符的问题:

if type(o) == "string" then

    io.write("[[", o, "]]")

千万不要这样做!双引号是针对手写的字符串的而不是针对自动产生的字符串。如果有人恶意的引导你的程序去使用" ]]..os.execute('rm *')..[[ "这样的方式去保存某些东西(比如它可能提供字符串作为地址)你最终的chunk将是这个样子:

varname = [[ ]]..os.execute('rm *')..[[ ]]

如果你load这个数据,运行结果可想而知的。为了以安全的方式引用任意的字符串,string标准库提供了格式化函数专门提供"%q"选项。它可以使用双引号表示字符串并且可以正确的处理包含引号和换行等特殊字符的字符串。这样一来,我们的序列化函数可以写为:

function serialize (o)

    if type(o) == "number" then

       io.write(o)

    elseif type(o) == "string" then

       io.write(string.format("%q", o))

    else ...

end


相关链接:
lua程序设计目录 - 中国lua开发者 - lua论坛