zoukankan      html  css  js  c++  java
  • chapter 12_1 数据文件

      Lua的一个重要特性,就是可以作为配置文件,利用到table构造式来定义一种文件格式。

    只需要在写数据时做一点额外的工作,读取数据就会变得相当容易。也就是将数据作为Lua代码输出。

    当运行这些代码时,程序也就读取了数据。而table的构造式可以使这些输出代码看上去更像是一个普通的数据文件。

    如果是为了应用而创建数据文件的话,那么就可以使用Lua的构造式作为格式。在这种格式中,每条数据记录表示为

    一个Lua构造式:

    local mode = {}
    function Module(b) 
        if b.name then
            mode[b.name] = b
        end
    end
    
    dofile("data")
    
    ---[[ data 文件
    Module{
        name             = "video",
        frame_rate       = 25,
        frame_type       = "H264",
        frame_bitrate    = 2048,
        frame_interval   = 30,
        frame_control    = "vbr", -- cbr
    }
    
    Module{
        name             = "audio",
        audio_type       = "acc",
        sampling_rate    = 8000,     --采样率
        audio_channel    = "stereo", --立体声
    }

    Module{<code>}与Module({<code>})是完全等价的,都是以一个table作为参数来调用Module函数。

    因此,上面的这段数据也是一个Lua程序。为了读取该文件,我们只需要定义一个合适的Module,然后运行就可以了。

    这种格式就是“自描述的数据”格式,其中每项数据都伴随一个表示其含义的简短描述。比CSV或其他紧缩格式更具可读性。

    当需要修改时,可以在基本格式中作一个细小的改动,而不需要同时改变数据文件。

    例如要新增一个字段,只需修改读取程序中的一小块就可以了,内容就是当该字段不存在时提供一个默认值。

    使用名值对格式,可以打印收集mode的程序:

    for name in pairs(mode) do
        print (name)
    end

    Lua不仅运行速度快,而且编译速度也快。

    自从Lua创建之处就把数据描述作为Lua的主要应用之一来考虑。

    串行化

      通常需要串行化一些数据,也就是将数据转换为一个字节流或字符流。然后就可以将其存储到一个文件中,或者通过

    网络连接发送出去。串行化后的数据可以用Lua代码来表示,这样当运行这些代码时,存储的数据就可以在读取程序中得到重构。

      如果想要恢复一个全局变量的值,那么串行化的结果或许可以是"varname = <exp>",其中<exp>是一段用于创建该值得Lua代码。

    而varname只是一个简单的标识符。

    下面演示如何编写创建一个值的代码,例如对于一个数字值,方法如下:

    function serialize(o)
        if type(o) == "number" then
            io.write(string.format("%a",o))
        else
            <other cases>
        end
    end

    对于一个字符串值,方法如下:

    if type(o) == "string" then
        io.write("'",o,"'")

    如果字符串包括特殊字符(引号或者换行符),那么最终代码就不是一段有效的Lua程序了。

    但是可以使用另一种方法:

    if type(o) == "string" then
        io.write("[[ ",o,"]] ")

    注意,如果恶意的用户故意使其字符串为" ]] .. os.execute('rm *').. [[ ",那么最终保存下来的结果变成:

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

    如果加载这个数据,将会出现不可估量的后果。

    一个简单的办法:用“%q”来使用string.format函数。这样它就会用双引号来括住字符串,并且正确地转移其中的双引号和换行符。

    a = 'a "problematic" \string'
    print(string.format("%q",a))  --> "a "problemmatic" \string"

    通过这个特性,serialize函数可以改为:

    function serialize(o)
        if type(o) == "number" then
            io.write(o)
        elseif type(o) == "string" then
            io.write(string.format("%q",o))
        else 
            <other cases>
        end
    end

    Lua5.1还提供了另一种可以以一种安全的方法来括住任意字符串的方法。

    用“[=[ ... ]=]” 标记长字符串。这种方式主要是为手写的代码提供方便的,通过它就不需要改变任何字符串的内容了。

    在自动生成的代码中,要转移那些问题字符,还是使用string.format与“%q”选项更为方便。

  • 相关阅读:
    C#中的async和await
    Windows 10 error code 0x80072efd
    Winform中调用js函数
    Windows 10 x64 安装 Visual Basic 6.0 SP6
    用谷歌浏览器来当手机模拟器
    Windows 10 解决 0x80070021 错误
    正则匹配所有中英文标点
    本地网站部署注意细节
    电信光猫 路由+拨号混合设置 备忘
    Restful 支持 自定义序列化
  • 原文地址:https://www.cnblogs.com/daiker/p/5842049.html
Copyright © 2011-2022 走看看