How to save tables in files

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
pauls313
Citizen
Posts: 50
Joined: Tue Aug 02, 2016 3:07 am

How to save tables in files

Post by pauls313 »

I'm making a tilebased game, and to make things easier i'm making a map editor. But once I finish a map using it, how can I save it to use later? I read about writing to files, but I want to save it as a TABLE, so I can simply access it later.
User avatar
HugoBDesigner
Party member
Posts: 403
Joined: Mon Feb 24, 2014 6:54 pm
Location: Above the Pocket Dimension
Contact:

Re: How to save tables in files

Post by HugoBDesigner »

Depends on the complexity of your table. Here's a small function to convert variables into string (doesn't work for self-containing tables or functions, so be aware of that!)

Code: Select all

function varToString(var)
	if type(var) == "string" then
		return "\"" .. var .. "\""
	elseif type(var) ~= "table" then
		return tostring(var)
	else
		local ret = "{ "
		local ts = {}
		local ti = {}
		for i, v in pairs(var) do
			if type(i) == "string" then
				table.insert(ts, i)
			else
				table.insert(ti, i)
			end
		end
		table.sort(ti)
		table.sort(ts)
		
		local comma = ""
		if #ti >= 1 then
			for i, v in ipairs(ti) do
				ret = ret .. comma .. varToString(var[v])
				comma = ", "
			end
		end
		
		if #ts >= 1 then
			for i, v in ipairs(ts) do
				ret = ret .. comma .. "[\"" .. v .. "\"] = " .. varToString(var[v])
				comma = ", "
			end
		end
		
		return ret .. "}"
	end
end
The table is barely humanly readable (can be fixed by tweaking my code a LOT), but it should work. Just save your variable like this:

Code: Select all

love.filesystem.write("YOUR FILE PATH", "VARNAME = " .. varToString(VARNAME))
Then, to load it later, just do this:

Code: Select all

love.filesystem.load("YOUR FILE PATH")()
It's probably not the most optimal method. I'm sure a more experienced programmer will have a better solution :rofl:


EDIT: Additionally, a much simpler approach would be using JSON to load and save your data.
@HugoBDesigner - Twitter
HugoBDesigner - Blog
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: How to save tables in files

Post by zorg »

@HugoBDesigner: I disagree since lua is already a fine scripting language itself, why combine it with JSON or XML and such monstrosities? :3
Apart from that, encoding and decoding between different representations cuts processing speed, and lua is perfectly capable to loadstring stuff in "instantly".

@pauls313:Writing to files means exactly that, writing data to files.
A table is data as well. Unless you mean you want to keep the same representation as you'd have in your code, in which case, there are a few serializer libraries that do just that, like Ser (even though it's deprecated, the format it exports is somewhat readable table structure, that you can simply load back into lua anytime; binser/bitser/etc. function similarly, but store the data in different ways, probably saving space.

You weren't really exact on what you meant, so i tried to explain it in some detail.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: How to save tables in files

Post by Nixola »

zorg wrote:@HugoBDesigner: I disagree since lua is already a fine scripting language itself, why combine it with JSON or XML and such monstrosities? :3
Apart from that, encoding and decoding between different representations cuts processing speed, and lua is perfectly capable to loadstring stuff in "instantly".
Because loading Lua code that way can be unsafe; data storage formats (as JSON, XML are) are not. Of course, if safety isn't a concern, exporting Lua code is a perfectly valid option.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to save tables in files

Post by pgimeno »

There are two serializing libraries designed for native Lua tables that I am aware of, that don't load their output as Lua code: bitser and Smallfolk, both by forum member Robin. bitser is more compact, so it's great for big amounts of data, while Smallfolk uses text output, easier to read and modify. Unfortunately, for some reason Smallfolk has been deprecated, even if it is (to my knowledge) the only library in its category.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: How to save tables in files

Post by airstruck »

Nixola wrote:Because loading Lua code that way can be unsafe [...] Of course, if safety isn't a concern, exporting Lua code is a perfectly valid option.
It can be unsafe but doesn't have to be. It's still a valid option even if safety is a concern.

Code: Select all

local t = setfenv(loadstring(data), {})() 
I wouldn't call that unsafe. About the worst it could do is go into an infinite loop so you have to force kill it. Annoying, but not unsafe.

Hitting the local variable limit or some other language limitation might be a bigger concern.
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: How to save tables in files

Post by Positive07 »

Kikito's sandbox.lua handles infinite loops with [manual]debug.sethook[/manual]

If you make a hook function that errors when called and put a count equal to the number of instructions the file may call then you get a quota limit. That is the idea at least, and it works in that project I posted

Code: Select all

local quota = 5000

local timeup = function ()
   debug.sethook()
   error("Quota exceeded: "..tostring(quota), 2)
end

local f = setfenv(loadstring(data), {})

local wrapf = function (...)
   debug.sethook(timeup, "", quota)
   local value = f(...)
   debug.sethook()
   return value
end

local err, value = pcall(wrapf)
Something like that should be pretty safe
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: How to save tables in files

Post by zorg »

Nixola wrote:
zorg wrote:@HugoBDesigner: I disagree since lua is already a fine scripting language itself, why combine it with JSON or XML and such monstrosities? :3
Apart from that, encoding and decoding between different representations cuts processing speed, and lua is perfectly capable to loadstring stuff in "instantly".
Because loading Lua code that way can be unsafe; data storage formats (as JSON, XML are) are not. Of course, if safety isn't a concern, exporting Lua code is a perfectly valid option.
I agree that it can be unsafe, but if it isn't stated otherwise, i always assume that we're talking about a scenario where the game is singleplayer, the files are local, and the user does not mess with them manually (or if they do, the code will include assertions or some checks to error gracefully). Under those criteria, it simply does not matter. :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: How to save tables in files

Post by ivan »

As Zorg mentioned, Ser is a great library but to be honest I've been moving away from serialization - primarily because it's much easier to just avoid nested tables and simply save a list of key-value pairs. Generally speaking you shouldn't need nested tables for something as simple as save files. For map files like in this case, I would recommend a custom format altogether - the simplest solution being TXT, where each line in the TXT file is a row on the map.
As for loading Lua files - it can be unsafe depending on the location where the files are loaded from. I would consider the appdata directory unsafe because anybody can write stuff there. Of course, there are ways to load Lua code even from un-trusted locations. This should only be a concern for commercial games.
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: How to save tables in files

Post by pgimeno »

ivan wrote:As Zorg mentioned, Ser is a great library but to be honest I've been moving away from serialization - primarily because it's much easier to just avoid nested tables and simply save a list of key-value pairs. Generally speaking you shouldn't need nested tables for something as simple as save files.
Well, if you're doing a memory or pong game, maybe. But as the state of the game becomes more complex, if you're flattening the state to save it, you're basically manually doing the job of the serializer.

Take for example Thrust II Reloaded. I need to keep the state of the player's ship, of the cable, of each of the enemies, of each of the orbs, and various counters. Everything that needs to be saved is kept in a table called game.state. Then on save I just dump that table, and restore it on load. Save and load would be much more complicated if I had to flatten all that data prior to saving and reorganizing it into a table hierarchy after loading.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 215 guests