Storage - Save data to files

Showcase your libraries, tools and other projects that help your fellow love users.
Anickyan
Prole
Posts: 27
Joined: Sun Aug 05, 2012 8:42 am

Storage - Save data to files

Post by Anickyan »

I made this little utility, which allows you to easily save data to files.

Data types supported:
- Strings
- Functions --- VIA STRINGS ONLY
- Numbers
- Booleans
- Tables

Data types NOT supported:
- Userdata

Functions that can be used:

Code: Select all

storage.save(path, value) -- path:string, value:string/boolean/number/table | saves <value> to <path>
storage.load(path) -- path:string | loads and returns a value(string/boolean/number/table/function) from <path>
storage.readTable(t) -- t:table | returns a string containing the table
This utility also allows you to use the flib utility, which I wrote some time ago. This allows you to do some easy file manipulation.
These are the functions in flib(taken from another post, so not too detailed)

Code: Select all

flib.exists(path) --Returns true if path exists, and is a file
flib.getTable(path) --Returns a table with all the lines
flib.getLine(path, n) --Returns the Nth line
flib.getText(path) --Returns all the text in the file
flib.fwrite(path, text) --Writes text in a file
flib.fappend(path, text) --Appends text to a file
flib.fwriteAtStart(path, text) --Writes text at the start of a file
flib.fwriteFromTable(path, table) --Writes each field in table as a line in the file
flib.fappendFromTable(path, table) --Appends to a file with each field in table as a line
flib.fwriteAtStartFromTable(path, table) --Writes at the start of a file with each field in table as a line
flib.fwriteFromLine(path, n, text) --Writes text from Nth line, and keeps everything beneath the Nth line
flib.fwriteFromLineFromTable(path, line, table) --Writes from Nth line with each field in table as a line, and keeps everything beneath the Nth line

flib.replaceLine(path, line, text) --Replaces the Nth line in a file with text
flib.getName(path) --Returns the name of the file, without the path
flib.getPath(path) --Returns the path of the file, without the name
flib.fremove(path) --Removes a file
flib.getFiles(path) -- Returns a table with all of the files in path/. REQUIRES LÖVE
flib.isDir(path) -- Returns true if path is a directory, false otherwise. REQUIRES LÖVE
-----------------------------------------------------------------------------------------

Code(just copy into a file, and name it anything):

Code: Select all

flib = {}

function flib.exists(path)
	if love then
		return love.filesystem.exists(path)
	else
		local file = io.open(path, "r")
		if file ~= nil then
			file:close()
			return true
		end
		
		return false
	end
end

--[[
function flib.exists(path)
	if love then
		return love.filesystem.exists(path)
	else
		print "user pls"
		os.exit()
	end
end
]]

function flib.getTable(path)
	if exists(path) then
		local file = io.open(path, "r")
		local lines = {}
		local i = 1
		local line = file:read("*l")
		while line ~= nil do
			lines[i] = line
			line = file:read("*l")
			i = i + 1
		end
		file:close()
		return lines
	end
	return {}
end

function flib.getLine(path, n)
	if exists(path) then
		local lines = getTable(path)
		return lines[n]
	end
	return ""
end

function flib.getText(path)
	if exists(path) then
		local file = assert(io.open(path, "r"))
		return file:read("*a")
	end
	return ""
end

function flib.fappend(path, text)
	local file = assert(io.open(path, "a"))
	file:write(text.."\n")
	file:close()
end 

function flib.fwrite(path, text)
	local file = assert(io.open(path, "w"))
	file:write(text)
	file:close()
end

function flib.fwriteAtStart(path, text)
	local _text = getText(path)
	fwrite(path, text.."\n".._text)
end

function flib.fwriteFromTable(path, t)
	local text = ""
	for _, line in pairs(t) do
		text = text..line.."\n"
	end
	fwrite(path, text)
end

function flib.fappendFromTable(path, t)
	local text = ""
	for _, line in pairs(t) do
		text = text..line.."\n"
	end
	fappend(path, text)
end 

function flib.fwriteAtStartFromTable(path, t)
	local text = ""
	for _, line in pairs(t) do
		text = text..line.."\n"
	end
	fwriteAtStart(path, text)
end

function flib.fwriteFromLine(path, n, text)
	if exists(path) then
		local lines = getTable(path)
		local file = io.open(path, "w")
		local count = 0
		
		for i = 1, n do
			file:write(lines[i].."\n")
			count = count + 1
		end
		
		file:write(text.."\n")
		
		for i = n + 1, #lines + count do
			if lines[i] ~= nil then
				file:write(lines[i].."\n")
			end
		end
		
		file:close()
	end
end

function flib.fwriteFromLineFromTable(path, n, _lines)
	if exists(path) then
		local lines = getTable(path)
		local file = io.open(path, "w")
		local count = 0
		
		for i = 1, n do
			file:write(lines[i].."\n")
			count = count + 1
		end
		
		for _, line in pairs(_lines) do
			file:write(tostring(line).."\n")
		end
		
		for i = n + 1, #lines + count do
			if lines[i] ~= nil then
				file:write(lines[i].."\n")
			end
		end
		
		file:close()
	end
end

function flib.replaceLine(path, n, text)
	local lines = getTable(path)
	lines[n] = text
	fwriteFromTable(path, lines)
end

function flib.getName(path)
	if exists(path) then
		local lastSlashPos = 1
		for i = 1, path:len() do
			if path:sub(i, i) == "/" then
				lastSlashPos = i
			end
		end
		
		return path:sub(lastSlashPos + 1)
	end
	return ""
end

function flib.getPath(path)
	if exists(path) then
		local lastSlashPos = 1
		for i = 1, path:len() do
			if path:sub(i, i) == "/" then
				lastSlashPos = i
			end
		end
		
		return path:sub(1, lastSlashPos)
	end
	return ""
end

function flib.fremove(path)
	if os.remove then
		os.remove(path)
	else
		fs.remove(path)
	end
end

function flib.getFiles(path)
	if love then
		return love.filesystem.enumerate(path)
	else
		print "user pls"
		os.exit()
	end
end

function flib.isDir(path)
	if love then
		return love.filesystem.isDirectory(path)
	else
		print "user pls"
		os.exit()
	end
end

storage = {}

local function readTable(t)
	local s = "{"

	for k, v in pairs(t) do
		if type(k) == "string" then
			s = s .. tostring(k) .. " = "
		end

		if type(v) == "string" then
			s = s .. "\"" .. tostring(v) .. "\"" .. ", " 
		elseif type(v) == "number" or type(v) == "boolean" then
			s = s .. tostring(v) .. ", "
		elseif type(v) == "table" then
			s = s .. readTable(v) .. ", "
		end
	end

	s = s .. "\"end\"}"
	return s
end

function storage.save(path, value)
	if type(value) == "number" or type(value) == "boolean" then
		local s = tostring(value)
		flib.fwrite(path, "return " .. s)
	elseif type(value) == "string" then
		local s = tostring(value)
		s = "\"" .. s .. "\""
		flib.fwrite(path, "return " .. s)
	elseif type(value) == "table" then
		local s = readTable(value)
		flib.fwrite(path, "return " .. s)
	end
end

function storage.load(path)
	if not storage.exists(path) then
		error "Bad argument #1 to 'storage.new()': file does not exist"
	end

	return dofile(path)
end

function storage.readTable(t)
	return readTable(t)
end
User avatar
qaisjp
Party member
Posts: 490
Joined: Tue Sep 04, 2012 10:49 am
Location: United Kingdom
Contact:

Re: Storage - Save data to files

Post by qaisjp »

you can store functions by using string.dump(fn), this returns a binary version of the function which is stored in a string and can be put in files.
Lua is not an acronym.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Storage - Save data to files

Post by Roland_Yonaba »

qaisjp wrote:you can store functions by using string.dump(fn), this returns a binary version of the function which is stored in a string and can be put in files.
Just works for functions without upvalues, though.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: Storage - Save data to files

Post by Nixola »

What does upvalue mean?

EDIT: Karma to you, Qais
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Storage - Save data to files

Post by Roland_Yonaba »

I suck at explaining technical terms, but i'll rather give a self-explanatory example.
Upvalues can be considered as 'external local variables', in a closure.
Say that you want to make a counter:

Code: Select all

count = 0

function counter ()
  count = count + 1
end 
counter() -- count is 1
counter() -- count is 2
Problem is the variable count is global here, therefore can be accessed by any other function.
So, we can enclose it inside the scope of a function, and return another one who will still have access to it.

Code: Select all

function new_counter ()
  local count = 0
  -- returns a function which accesses to local count
  return function ()
    count = count + 1
   print('count is', count)
  end
end

counter = new_counter ()
counter() -- count is 1
counter() -- count is 2

To the point of view of counter, variable count is neither local nor global. It is an upvalue.
User avatar
slime
Solid Snayke
Posts: 3163
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Storage - Save data to files

Post by slime »

qaisjp wrote:you can store functions by using string.dump(fn), this returns a binary version of the function which is stored in a string and can be put in files.
string.dump is not portable between architectures (except when using LuaJIT), Lua versions besides revisions, or between Lua and LuaJIT.
Anickyan
Prole
Posts: 27
Joined: Sun Aug 05, 2012 8:42 am

Re: Storage - Save data to files

Post by Anickyan »

And that's the reason, that I didn't use string.dump :)

Anyway, do you like it?
DarthGrover
Prole
Posts: 16
Joined: Wed Feb 05, 2014 11:31 pm
Location: Ohio USA

Re: Storage - Save data to files --permission denied

Post by DarthGrover »

Thanks for this library. I think it really going to help me a lot. But when I tried:

storage.save("myfile.txt", mytable)
I get an error saying permission denied
myfile is in the root folder i tried it as .lua and .txt

I think I am missing a basic concept here.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Storage - Save data to files

Post by Robin »

For some reason this library mixes love.filesystem with Lua io, which doesn't work. I suggest using something else.
Help us help you: attach a .love.
DarthGrover
Prole
Posts: 16
Joined: Wed Feb 05, 2014 11:31 pm
Location: Ohio USA

Re: Storage - Save data to files

Post by DarthGrover »

thanks. can you suggest a different library?
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests