Lua文件处理

本文介绍Lua语言中的文件读写操作及限制,并详细探讨了如何序列化Lua中的表,包括非循环表和带有循环引用的表的处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一。文件读存:

  -- 似乎不支持大文件(不能超过9k?):   function opensavetest()   local file = io.open("c://in.lua", "r");   if(file) then   local data = file:read("*a"); -- i've also tried "*all" as described in PIL   file:close();   file = io.open("c://out.lua", "w");   if(file) then   file:write(data);   file:close();   end   end   end   opensavetest();

  二。非循环表格处理(见program in lua):

  HERO = 1 Monster = 2 Building = 3 SumUnit = 4   cha = {}   cha[1] =   {   basic =   {   Name = "农民" , --角色名称   cha_type = HERO --角色模型类型   } ,   Combat =   {   acquire = 600.00 , --主动攻击范围   basic_def = 10 --基础防御   }   }   function serialize2( o)   if type(o) == "number" then   g_file:write(o)   elseif type(o) == "string" then   g_file:write(string.format("%q", o))   elseif type(o) == "table" then   g_file:write("{/n")   for k,v in pairs(o) do   g_file:write(" [")   serialize2(k)   g_file:write("] = ")   serialize2(v)   g_file:write(",/n")   end   g_file:write("}/n")   else   error("cannot serialize a " .. type(o))   end   end   function savetest ()   if g_file == nil then   print("error int 'savetest()'");   return;   end   g_file:write("cha = {}/n")   g_file:write("cha[1] = {/n")   serialize2( cha[1] );   g_file:write("}/n")   end   g_file = io.open("c://tt.lua", "w");   savetest();   g_file:close()

  三。原program in lua中的保存带/不带循环的table

  12.1.1 保存不带循环的table

  我们下一个艰巨的任务是保存表。根据表的结构不同,采取的方法也有很多。没有一种单一的算法对所有情况都能很好地解决问题。简单的表不仅需要简单的算法而且输出文件也需要看起来美观。

  我们第一次尝试如下:

  function serialize (o)   if type(o) == "number" then   io.write(o)   elseif type(o) == "string" then   io.write(string.format("%q", o))   elseif type(o) == "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(" ", k, " = ")

  改为

  io.write(" [")

  serialize(k)

  io.write("] = ")

  这样一来,我们改善了我们的函数的健壮性,比较一下两次的结果:

  -- result of serialize{a=12, b='Lua', key='another "one"'}   -- 第一个版本   {   a = 12,   b = "Lua",   key = "another /"one/"",   }   -- 第二个版本   {   ["a"] = 12,   ["b"] = "Lua",   ["key"] = "another /"one/"",   }

  我们可以通过测试每一种情况,看是否需要方括号,另外,我们将这个问题留作一个练习给大家。

  12.1.2 保存带有循环的table

  针对普通拓扑概念上的带有循环表和共享子表的table,我们需要另外一种不同的方法来处理。构造器不能很好地解决这种情况,我们不使用。为了表示循环我们需要将表名记录下来,下面我们的函数有两个参数:table和对应的名字。另外,我们还必须记录已经保存过的table以防止由于循环而被重复保存。我们使用一个额外的table来记录保存过的表的轨迹,这个表的下表索引为table,而值为对应的表名。

  我们做一个限制:要保存的table只有一个字符串或者数字关键字。下面的这个函数序列化基本类型并返回结果。

  function basicSerialize (o)   if type(o) == "number" then   return tostring(o)   else -- assume it is a string   return string.format("%q", o)   end   end

  关键内容在接下来的这个函数,saved这个参数是上面提到的记录已经保存的表的踪迹的table。

  function save (name, value, saved)   saved = saved or {} -- initial value   io.write(name, " = ")   if type(value) == "number" or type(value) == "string" then   io.write(basicSerialize(value), "/n")   elseif type(value) == "table" then   if saved[value] then -- value already saved?   -- use its previous name   io.write(saved[value], "/n")   else   saved[value] = name -- save name for next time   io.write("{}/n") -- create a new table   for k,v in pairs(value) do -- save its fields   local fieldname = string.format("%s[%s]", name,   basicSerialize(k))   save(fieldname, v, saved)   end   end   else   error("cannot save a " .. type(value))   end   end

  举个例子:

  我们将要保存的table为:

  a = {x=1, y=2; {3,4,5}}

  a[2] = a -- cycle

  a.z = a[1] -- shared sub-table

  调用save('a', a)之后结果为:

  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]

  (实际的顺序可能有所变化,它依赖于table遍历的顺序,不过,这个算法保证了一个新的定义中需要的前面的节点都已经被定义过)

  如果我们想保存带有共享部分的表,我们可以使用同样table的saved参数调用save函数,例如我们创建下面两个表:

  a = {{"one", "two"}, 3}

  b = {k = a[1]}

  保存它们:

  save('a', a)

  save('b', b)

  结果将分别包含相同部分:

  a = {}

  a[1] = {}

  a[1][1] = "one"

  a[1][2] = "two"

  a[2] = 3

  b = {}

  b["k"] = {}

  b["k"][1] = "one"

  b["k"][2] = "two"

  然而如果我们使用同一个saved表来调用save函数:

  local t = {}

  save('a', a, t)

  save('b', b, t)

  结果将共享相同部分:

  a = {}

  a[1] = {}

  a[1][1] = "one"

  a[1][2] = "two"

  a[2] = 3

  b = {}

  b["k"] = a[1]

  上面这种方法是Lua中常用的方法,当然也有其他一些方法可以解决问题。比如,我们可以不使用全局变量名来保存,即使用封包,用chunk构造一个local值然后返回之;通过构造一张表,每张表名与其对应的函数对应起来等。Lua给予你权力,由你决定如何实现。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值