• Lua文件处理
    时间:2008-09-03   作者:佚名   出处:互联网

    一。文件读存:
    -- 似乎不支持大文件(不能超过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给予你权力,由你决定如何实现。

    网友留言/评论

    我要留言/评论