将表保存到文件

lua-users home
wiki

将表保存到文件;从文件加载表

特点

文件:wiki_insecure/users/chill/table.save-1.0.lua

注意:不适用于大型表。保存包含 100,000 个子表(每个子表包含 25 个字段,其中 1 个为短文本行,24 个为数值条目)的表可以正常工作。保存更大的表时,性能会急剧下降。尝试读取时,会遇到“常量表溢出”错误。对于较小的表,它似乎可以正常工作。特别是考虑到它是一个针对您需求的剪切粘贴解决方案。有一些测试代码表明您可以很好地保存如此大的表,当然,这也是机器问题。

--[[
   Save Table to File
   Load Table from File
   v 1.0
   
   Lua 5.2 compatible
   
   Only Saves Tables, Numbers and Strings
   Insides Table References are saved
   Does not save Userdata, Metatables, Functions and indices of these
   ----------------------------------------------------
   table.save( table , filename )
   
   on failure: returns an error msg
   
   ----------------------------------------------------
   table.load( filename or stringtable )
   
   Loads a table that has been saved via the table.save function
   
   on success: returns a previously saved table
   on failure: returns as second argument an error msg
   ----------------------------------------------------
   
   Licensed under the same terms as Lua itself.
]]--
do
   -- declare local variables
   --// exportstring( string )
   --// returns a "Lua" portable version of the string
   local function exportstring( s )
      return string.format("%q", s)
   end

   --// The Save Function
   function table.save(  tbl,filename )
      local charS,charE = "   ","\n"
      local file,err = io.open( filename, "wb" )
      if err then return err end

      -- initiate variables for save procedure
      local tables,lookup = { tbl },{ [tbl] = 1 }
      file:write( "return {"..charE )

      for idx,t in ipairs( tables ) do
         file:write( "-- Table: {"..idx.."}"..charE )
         file:write( "{"..charE )
         local thandled = {}

         for i,v in ipairs( t ) do
            thandled[i] = true
            local stype = type( v )
            -- only handle value
            if stype == "table" then
               if not lookup[v] then
                  table.insert( tables, v )
                  lookup[v] = #tables
               end
               file:write( charS.."{"..lookup[v].."},"..charE )
            elseif stype == "string" then
               file:write(  charS..exportstring( v )..","..charE )
            elseif stype == "number" then
               file:write(  charS..tostring( v )..","..charE )
            end
         end

         for i,v in pairs( t ) do
            -- escape handled values
            if (not thandled[i]) then
            
               local str = ""
               local stype = type( i )
               -- handle index
               if stype == "table" then
                  if not lookup[i] then
                     table.insert( tables,i )
                     lookup[i] = #tables
                  end
                  str = charS.."[{"..lookup[i].."}]="
               elseif stype == "string" then
                  str = charS.."["..exportstring( i ).."]="
               elseif stype == "number" then
                  str = charS.."["..tostring( i ).."]="
               end
            
               if str ~= "" then
                  stype = type( v )
                  -- handle value
                  if stype == "table" then
                     if not lookup[v] then
                        table.insert( tables,v )
                        lookup[v] = #tables
                     end
                     file:write( str.."{"..lookup[v].."},"..charE )
                  elseif stype == "string" then
                     file:write( str..exportstring( v )..","..charE )
                  elseif stype == "number" then
                     file:write( str..tostring( v )..","..charE )
                  end
               end
            end
         end
         file:write( "},"..charE )
      end
      file:write( "}" )
      file:close()
   end
   
   --// The Load Function
   function table.load( sfile )
      local ftables,err = loadfile( sfile )
      if err then return _,err end
      local tables = ftables()
      for idx = 1,#tables do
         local tolinki = {}
         for i,v in pairs( tables[idx] ) do
            if type( v ) == "table" then
               tables[idx][i] = tables[v[1]]
            end
            if type( i ) == "table" and tables[i[1]] then
               table.insert( tolinki,{ i,tables[i[1]] } )
            end
         end
         -- link indices
         for _,v in ipairs( tolinki ) do
            tables[idx][v[2]],tables[idx][v[1]] =  tables[idx][v[1]],nil
         end
      end
      return tables[1]
   end
-- close do
end

-- ChillCode
测试代码
dofile( "table.save-1.0.lua" )

function Main()
     
print( "Serialise Test ..." )
   
local t = {}
t.a = 1
t.b = 2
t.c = {}
-- self reference
t.c.a = t
t.inass = { 1,2,3,4,5,6,7,8,9,10 }
t.inasst = { {1},{2},{3},{4},{5},{6},{7},{8},{9},{10} }
-- random
t.f = { [{ a = 5, b = 7, }] = "helloooooooo", [{ 1,2,3, m = 5, 5,6,7 }] = "A Table", }

t.func = function(x,y)
   print( "Hello\nWorld" )
   local sum = x+y
   return sum
end

-- get test string, not string.char(26)
local str = ""
for i = 0, 255 do
   str = str..string.char( i )
end
t.lstri = { [str] = 1 }
t.lstrv = str

local function test() print("Hello") end

t[test] = 1

   
print( "\n## BEFORE SAVE ##" )

printtbl( t )

--// test save to file
assert( table.save( t, "test_tbl.lua" ) == nil )
   
-- load table from file
local t2,err = table.load( "test_tbl.lua" )

assert( err == nil )


print( "\n## AFTER SAVE ##" )

print( "\n## LOAD FROM FILE ##" )

printtbl( t2 )

print( "\n//Test References" )
   
assert( t2.c.a == t2 )
   
print( "\n//Test Long string" )

assert( t.lstrv == t2.lstrv )

print( "\n//Test Function\n\n" )

assert( t2.func == nil )

print( "\n*** Test SUCCESSFUL ***" )

end

function printtbl( t,tab,lookup )
   local lookup = lookup or { [t] = 1 }
   local tab = tab or ""
   for i,v in pairs( t ) do
      print( tab..tostring(i), v )
      if type(i) == "table" and not lookup[i] then
         lookup[i] = 1
         print( tab.."Table: i" )
         printtbl( i,tab.."\t",lookup )
      end
      if type(v) == "table" and not lookup[v] then
         lookup[v] = 1
         print( tab.."Table: v" )
         printtbl( v,tab.."\t",lookup )
      end
   end
end

function SaveHugeTable()

   local _t = {}

   for i=1,1000000 do

      local __t = {}
      table.insert(_t, __t)
      table.insert(__t, "THIS IS A STRING WITH A FEW CHARS")
      for i=1,30 do
         table.insert(__t, i)
      end   
   end
   
   print("Built Hunge Table!")

   t1 = os.clock()
   assert( table.save( _t, "test_huge_tbl.lua" ) == nil )
   print("Done Saving: "..os.difftime(os.clock(), t1))
   
   _t = nil
   collectgarbage()
   
   t1 = os.clock()
   local t2,err = table.load( "test_huge_tbl.lua" )
   print("Done Loading: "..os.difftime(os.clock(), t1))
   
   print("Num: "..#t2)

   assert( err == nil )
   
   print( "\n*** Test SUCCESSFUL ***" )
   
   io.read()
end


Main()
--SaveHugeTable()

io.read()

另请参阅


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2013 年 8 月 7 日凌晨 3:19 GMT (差异)