Save Table To File


Save a Table to file; Load a Table from file

Characteristics:

Files:wiki_insecure/users/chill/table.save-1.0.lua

NOTICE: NOT suitable for huge tables. Saving a table containing 100.000 subtables with 25 (1 short text line and 24 numerical entries) fields works. Somewhere above that performance is disastrous when saving. And you get an "constant table overflow" error when you try to read it back. With smaller tables it seems to work. Especially considering it is a cut and past solution to your need. There is some test code that shows that you can very well save such big tables, of course this is also a machine issue.

--[[
 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
Testcode
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()

See Also


RecentChanges · preferences
edit · history
Last edited August 6, 2013 9:19 pm GMT (diff)

AltStyle によって変換されたページ (->オリジナル) /