第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还将帮助支持 Lua 项目。
用 Lua 编程 | ||
第二部分。表和对象 第 12 章。数据文件和持久性 |
在处理数据文件时,通常写数据比读回数据容易得多。当我们写文件时,我们可以完全控制正在发生的事情。另一方面,当我们读文件时,我们不知道会发生什么。除了正确文件可能包含的所有类型的数据之外,健壮的程序还应该优雅地处理错误文件。因此,编写健壮的输入例程总是很困难。
正如我们在 第 10.1 节 的示例中所看到的,表构造函数为文件格式提供了一个有趣的替代方案。在写数据时只需稍加工作,读取就会变得非常简单。这种技术是将我们的数据文件写成 Lua 代码,在运行时将数据构建到程序中。使用表构造函数,这些块看起来非常像一个普通数据文件。
和往常一样,让我们看一个示例来阐明问题。如果我们的数据文件采用预定义的格式,例如 CSV(逗号分隔值),我们几乎没有选择。(在 第 20 章 中,我们将看到如何在 Lua 中读取 CSV。)但是,如果我们要创建文件以供以后使用,我们可以使用 Lua 构造函数作为我们的格式,而不是 CSV。在这种格式中,我们将每条数据记录表示为一个 Lua 构造函数。我们不写类似于
Donald E. Knuth,Literate Programming,CSLI,1992 Jon Bentley,More Programming Pearls,Addison-Wesley,1990这样的内容,而是在数据文件中写
Entry{"Donald E. Knuth", "Literate Programming", "CSLI", 1992} Entry{"Jon Bentley", "More Programming Pearls", "Addison-Wesley", 1990}请记住,
Entry{...}
与 Entry({...})
相同,即调用函数 Entry
,其参数是一个表。因此,此先前的这部分数据是一个 Lua 程序。要读取此文件,我们只需要运行它,并为 Entry
提供一个明智的定义。例如,以下程序统计数据文件中的条目数
local count = 0 function Entry (b) count = count + 1 end dofile("data") print("number of entries: " .. count)下一个程序在文件中收集所有作者的姓名,然后打印出来。(作者姓名是每个条目中的第一个字段;因此,如果
b
是一个条目值,b[1]
是作者。)
local authors = {} -- a set to collect authors function Entry (b) authors[b[1]] = true end dofile("data") for name in pairs(authors) do print(name) end请注意这些程序片段中的事件驱动方法:
Entry
函数充当回调函数,在 dofile
期间针对数据文件中的每个条目调用该函数。
当文件大小不是一个大问题时,我们可以使用名称-值对进行表示
Entry{ author = "Donald E. Knuth", title = "Literate Programming", publisher = "CSLI", year = 1992 } Entry{ author = "Jon Bentley", title = "More Programming Pearls", publisher = "Addison-Wesley", year = 1990 }(如果此格式让您想起了 BibTeX,那不是巧合。BibTeX 是 Lua 中构造函数语法的灵感来源之一。)这种格式是我们所说的自描述数据格式,因为每条数据都附有对其含义的简短描述。自描述数据比 CSV 或其他紧凑表示法更具可读性(至少对人类而言);必要时,它们很容易手动编辑;并且它们允许我们进行小的修改,而无需更改数据文件。例如,如果我们添加一个新字段,我们只需要对读取程序进行一个小小的更改,以便在字段不存在时提供一个默认值。
使用 name-value 格式,我们收集作者的程序变为
local authors = {} -- a set to collect authors function Entry (b) authors[b.author] = true end dofile("data") for name in pairs(authors) do print(name) end现在字段的顺序无关紧要。即使某些条目没有作者,我们只需要更改
Entry
function Entry (b) if b.author then authors[b.author] = true end end
Lua 不仅运行速度快,而且编译速度也快。例如,用于列出作者的上述程序在 2 MB 的数据中运行时间不到一秒。同样,这不是偶然的。数据描述一直是 Lua 自创建以来主要应用之一,我们非常注意使其编译器对大块数据运行得很快。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |