Creating a save function

I have been with lua for almost two years now but I have never worked with io. How would I go about creating a save function that would require an array/dictionary to be passed to it and it would add it to a JSON array in a text file named “SaveFile.txt” and if its their first time saving the data it would create a blank JSON array. The best I have came up with was this

json = require "json" local path = system.pathForFile("SaveFile.txt", system.DocumentsDirectory)   function save(dataTable)      file = io.open(path, "w")      if file then           contents = file:read() or "[]"           encodedJson = json.encode(table.insert(json.decode(contents),dataTable))           file:write(encodedJson)           file:close()      else           print("File does not exist")           file:write("[]")      end end

Note* all it does is creates a text file with the source of “null” 

I worked on it a little bit more and now I believe I just have a logic error now.

local path = system.pathForFile("SaveFile2.txt", system.DocumentsDirectory)   json = require "json"   function save(dataTable)      file = io.open(path, "r+")      if file then       print("File Exists")           contents = file:read() or "[]"           newTable = json.decode(contents)           print("File Contents:" .. contents)           table.insert(newTable,dataTable)           encodedJson = json.encode(newTable)           file:write(encodedJson)      else           print("File does not exist")           file = io.open(path, "w")           a = {}           table.insert(a,dataTable)           file:write(json.encode(a))           print("Created new file \"SaveFile2.txt\" With source = " .. json.encode(a))      end     file:close() end   save({1,2,3})

now I ran this a few times and this is the output I got
 

22:11:53.293  File does not exist

22:11:53.303  Created new file “SaveFile2.txt” With source = [[1,2,3]]

22:12:12.569  File Exists

22:12:12.569  File Contents:[[1,2,3]]

22:12:16.626  File Exists

22:12:16.626  File Contents:[[1,2,3]][[1,2,3],[1,2,3]]

22:12:24.525  File Exists

22:12:24.525  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

22:12:34.756  File Exists

22:12:34.756  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

22:12:37.902  File Exists

22:12:37.902  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

22:12:40.739  File Exists

22:12:40.739  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

the end result of me running this should have looked like this

[[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]

I use this in my game

https://github.com/robmiracle/Simple-Table-Load-Save-Functions-for-Corona-SDK

thanks rob :slight_smile:

Thanks! This will work for android also right?

It works for all platforms except tvOS which doesn’t have a system.DocumentsDirectory to store things in.

I assume that people can open the saved json file and just edit it right?

You can encrypt the text in the file. I send you my version of the module when I get home. There is not much you can do to protect you files on android.

They would have to have a jailbroken or rooted device. They would have to go to effort to do so. A determined hacker will break any encryption you apply. But yes, the loadsave library writes in clear text and that file can be modified, if the person can get access to it.

Here is my code,

local M = {} local json = require("json") local \_defaultLocation = system.DocumentsDirectory local \_realDefaultLocation = \_defaultLocation local \_validLocations = { [system.DocumentsDirectory] = true, [system.CachesDirectory] = true, [system.TemporaryDirectory] = true } local enc1 = {86, 43, 70, 69, 14}; local function convert( chars, dist, inv ) return string.char( ( string.byte( chars ) - 32 + ( inv and -dist or dist ) ) % 95 + 32 ) end local crypt = function (str,k,inv) local enc= ""; for i=1,#str do if(#str-k[5] \>= i or not inv)then for inc=0,3 do if(i%4 == inc)then enc = enc .. convert(string.sub(str,i,i),k[inc+1],inv); break; end end end end if(not inv)then for i=1,k[5] do enc = enc .. string.char(math.random(32,126)); end end return enc; end function M.saveTable(t, filename, location) if location and (not \_validLocations[location]) then error("Attempted to save a table to an invalid location", 2) elseif not location then location = \_defaultLocation end local path = system.pathForFile( filename, location) local file = io.open(path, "w") if file then local contents = json.encode(t) local tempString = crypt(contents,enc1,false) file:write( tempString ) io.close( file ) return true else return false end end function M.loadTable(filename, location) if location and (not \_validLocations[location]) then error("Attempted to load a table from an invalid location", 2) elseif not location then location = \_defaultLocation end local path = system.pathForFile( filename, location) local contents = "" local myTable = {} local file = io.open( path, "r" ) if file then -- read all contents of file into a string local contents = file:read( "\*a" ) local tempString = crypt(contents,enc1,true) myTable = json.decode(tempString); io.close( file ) return myTable end return nil end function M.changeDefault(location) if location and (not location) then error("Attempted to change the default location to an invalid location", 2) elseif not location then location = \_realDefaultLocation end \_defaultLocation = location return true end function M.print\_r ( t ) local print\_r\_cache={} local function sub\_print\_r(t,indent) if (print\_r\_cache[tostring(t)]) then print(indent.."\*"..tostring(t)) else print\_r\_cache[tostring(t)]=true if (type(t)=="table") then for pos,val in pairs(t) do if (type(val)=="table") then print(indent.."["..pos.."] =\> "..tostring(t).." {") sub\_print\_r(val,indent..string.rep(" ",string.len(pos)+8)) print(indent..string.rep(" ",string.len(pos)+6).."}") elseif (type(val)=="string") then print(indent.."["..pos..'] =\> "'..val..'"') else print(indent.."["..pos.."] =\> "..tostring(val)) end end else print(indent..tostring(t)) end end end if (type(t)=="table") then print(tostring(t).." {") sub\_print\_r(t," ") print("}") else sub\_print\_r(t," ") end print() end M.printTable = M.print\_r return M

Of course I agree with rob. I would rather make it a little harder. This is the way do, I just want to stop the android user from going in do a quick modification. At the end of the day if someone wants to break into your house there is only so much you do while not having to unlock all the locks 

Well if they don’t know the encryption code then It would be one hard time trying to decrypt a file

Hard time yes, impossible no

Note* all it does is creates a text file with the source of “null” 

I worked on it a little bit more and now I believe I just have a logic error now.

local path = system.pathForFile("SaveFile2.txt", system.DocumentsDirectory)   json = require "json"   function save(dataTable)      file = io.open(path, "r+")      if file then       print("File Exists")           contents = file:read() or "[]"           newTable = json.decode(contents)           print("File Contents:" .. contents)           table.insert(newTable,dataTable)           encodedJson = json.encode(newTable)           file:write(encodedJson)      else           print("File does not exist")           file = io.open(path, "w")           a = {}           table.insert(a,dataTable)           file:write(json.encode(a))           print("Created new file \"SaveFile2.txt\" With source = " .. json.encode(a))      end     file:close() end   save({1,2,3})

now I ran this a few times and this is the output I got
 

22:11:53.293  File does not exist

22:11:53.303  Created new file “SaveFile2.txt” With source = [[1,2,3]]

22:12:12.569  File Exists

22:12:12.569  File Contents:[[1,2,3]]

22:12:16.626  File Exists

22:12:16.626  File Contents:[[1,2,3]][[1,2,3],[1,2,3]]

22:12:24.525  File Exists

22:12:24.525  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

22:12:34.756  File Exists

22:12:34.756  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

22:12:37.902  File Exists

22:12:37.902  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

22:12:40.739  File Exists

22:12:40.739  File Contents:[[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]][[1,2,3],[1,2,3]]

the end result of me running this should have looked like this

[[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]

I use this in my game

https://github.com/robmiracle/Simple-Table-Load-Save-Functions-for-Corona-SDK

thanks rob :slight_smile:

Thanks! This will work for android also right?

It works for all platforms except tvOS which doesn’t have a system.DocumentsDirectory to store things in.

I assume that people can open the saved json file and just edit it right?

You can encrypt the text in the file. I send you my version of the module when I get home. There is not much you can do to protect you files on android.

They would have to have a jailbroken or rooted device. They would have to go to effort to do so. A determined hacker will break any encryption you apply. But yes, the loadsave library writes in clear text and that file can be modified, if the person can get access to it.