Saving reading data files issue.

Hello,

I was trying to read/write files for my android application, everything works out in the simulator I have checked the sandbox and there is the file I am writing and everything, but when I try to do it in the device it does not work I have tried it in two different devices but I always get the same outcome I am using this file:

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

the loadsave.lua

I have only replaced this line of code to always point to my DocumentsDirectory
 

   local path = system.pathForFile( filename, system.DocumentsDirectory)

In both save and load functions, then in the file where I am trying to read the file I have the following code:

local loadsave = require("loadsave") local myTable myTable  = {} function scene:create( event ) myTable = loadsave.loadTable("myTable.json") end

Then in order for me to be able to write it I have the following code, this is called on some button click event:
 

function writeTable()  myTable.musicOn = false--musicOnBtn.isVisible  myTable.soundOn = false --SoundOnBtn.isVisible  loadsave.saveTable(myTable, "myTable.json") end

Then I have the following config in builds.seetings:
 

androidPermissions = { "android.permission.INTERNET", "android.permission.WRITE\_INTERNAL\_STORAGE",             "android.permission.WRITE\_EXTERNAL\_STORAGE",             "android.permission.ACCESS\_FINE\_LOCATION",             "android.permission.ACCESS\_COURSE\_LOCATION",            },

I read in some other forum that the android.permission.WRITE_INTERNAL_STORAGE may help, I also try removing it but I still get the same outcome.

the devices I am trying on don’t have sd storage just the local one phone or tablet storage, could it be this the problem?, what else can I do on this?
I really don’t know what to do now :confused:
 

Or is there anyway to set corona to save the data internally?

I use a modified version of this code, where I can save/load files on the device.

http://code.coronalabs.com/code/preference-library-save-data-files-tables-numbers-strings-and-boolean

hello! thank you very much yosu! I solved the problem by removing the json from the loadsave.lua file, instead what I did was to create an string function to handle the vars from the table and it’s working perfectly good in the device.

Thank you! (y) have nice coding! :slight_smile:

Jimmy

I am having the exact same issue you had, can you please post exactly how you modified the loadsave.lua code, also if you modified your main code too? I would be extreemly grateful for your help. :slight_smile:

What errors are you getting?  Please look at the console log and not just the popup alert.  There should be more information in your console log.  If you don’t know how to look at your logs, please read:  http://coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/

This code is pretty straight forward and you should not need to modify it.  It defaults to system.DocumentsDirectory already.  As far as android permissions, I don’t know that you need any special permissions for this.

Rob

Hi Rob

I saw your post on another thread and followed your advice in checking if the files exists and if it doesn’t create one:

playerData = loadsave.loadTable(“players.json”)
    if playerData == nil then
        playerData = {}
        playerScore = {}
        playerScore[1]=56300
        playerScore[2]=48660
        playerScore[3]=43900
        playerScore[4]=35100
        playerScore[5]=32400
        playerScore[6]=29500
        playerScore[7]=28700
        playerScore[8]=14300
        playerScore[9]=8200
        playerScore[10]=3900
        playerData.playerScore=playerScore
        storedPlayers = {}
        storedPlayers[1]=“Homer Simpson”
        storedPlayers[2]=“Dexter Morgan”
        playerData.storedPlayers=storedPlayers
        playerData.currentPlayer=“Dexter Morgan”
        playerData.numberOfPlayers=2
        playerLevel = {}
        playerLevel[1]=6
        playerLevel[2]=6
        playerLevel[3]=5
        playerLevel[4]=4
        playerLevel[5]=4
        playerLevel[6]=3
        playerLevel[7]=3
        playerLevel[8]=2
        playerLevel[9]=1
        playerLevel[10]=1
        playerData.playerLevel=playerLevel
        playerName = {}
        playerName[1]=“Filius Flitwick”
        playerName[2]=“Septima Vector”
        playerName[3]=“Charity Burbage”
        playerName[4]=“Severus Snape”
        playerName[5]=“Rolanda Hooch”
        playerName[6]=“Horace Slughorn”
        playerName[7]=“Wilhemina Plank”
        playerName[8]=“Pomona Sprout”
        playerName[9]=“Rubeus Hagrid”
        playerName[10]=“Poppy Pomfrey”
        playerData.playerName=playerName
        playerData.playerCount=10
        playerData.new=0
        loadsave.saveTable(playerData, “players.json”)
    end

I removed the players.json file from the sandbox documents folder and sure enough the file was created.

It worked on my phone but later on when a scene required another database I get this error:

06-21 03:44:01.915: I/Corona(15882): Runtime error
06-21 03:44:01.915: I/Corona(15882): …Documents\Corona Projects\Gameshow\loadQuestions.lua:13: attempt to index local ‘_file’ (a nil value)
06-21 03:44:01.915: I/Corona(15882): stack traceback:
06-21 03:44:01.915: I/Corona(15882):     [C]: ?
06-21 03:44:01.915: I/Corona(15882):     …Documents\Corona Projects\Gameshow\loadQuestions.lua:13: in main chunk
06-21 03:44:01.915: I/Corona(15882):     [C]: in function ‘require’
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:797>
06-21 03:44:01.915: I/Corona(15882):     (tail call): ?
06-21 03:44:01.915: I/Corona(15882):     (tail call): ?
06-21 03:44:01.915: I/Corona(15882):     …Documents\Corona Projects\Gameshow\questionRound.lua:54: in function <…Documents\Corona Projects\Gameshow\questionRound.lua:38>
06-21 03:44:01.915: I/Corona(15882):     ?: in function ‘dispatchEvent’
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:1096>
06-21 03:44:01.915: I/Corona(15882):     (tail call): ?
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:466>
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:218>
06-21 03:44:02.045: I/Corona(15882): Runtime error
06-21 03:44:02.045: I/Corona(15882): stack traceback:
06-21 03:44:02.045: I/Corona(15882):     [C]: ?
06-21 03:44:02.045: I/Corona(15882):     …Documents\Corona Projects\Gameshow\loadQuestions.lua:13: in main chunk
06-21 03:44:02.045: I/Corona(15882):     [C]: in function ‘require’
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:797>
06-21 03:44:02.045: I/Corona(15882):     (tail call): ?
06-21 03:44:02.045: I/Corona(15882):     (tail call): ?
06-21 03:44:02.045: I/Corona(15882):     …Documents\Corona Projects\Gameshow\questionRound.lua:54: in function <…Documents\Corona Projects\Gameshow\questionRound.lua:38>
06-21 03:44:02.045: I/Corona(15882):     ?: in function ‘dispatchEvent’
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:1096>
06-21 03:44:02.045: I/Corona(15882):     (tail call): ?
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:466>
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:218>
 

The error relates to my loadQuestions.lua module which only needs to read a text file, here’s the code:

local questions = {}

local _path = system.pathForFile( “MultipleChoice.txt”, system.DocumentsDirectory )
local _file = io.open( _path, “r” )
local counter = 1
local c=1
local question = {}
local ans_1 = {}
local ans_2 = {}
local ans_3 = {}
local ans_4 = {}

for line in _file:lines() do
   
    if counter == 1 then
      question[c] = line

      elseif counter == 2 then
      ans_1[c] = line

      elseif counter == 3 then
      ans_2[c] = line

      elseif counter == 4 then
      ans_3[c] = line

      elseif counter == 5 then
      ans_4[c] = line

   end

   counter = counter + 1

   if counter == 6 then
      counter = 1;
      c=c+1
   end

questions.c = c

end

questions.question = question
questions.ans_1 = ans_1
questions.ans_2 = ans_2
questions.ans_3 = ans_3
questions.ans_4 = ans_4

io.close( _file )
_file = nil
counter = nil
line = nil

   return questions

I’ve checked the spelling, why is my phone not finding the MultipleChoice.txt ? :huh:

This has nothing to do with my loadsave module.  I have to ask, is your MultipleChoice.txt in your system.DocumentsDirectory?  If so how does it get there?  The file doesn’t exist which is why you’re getting this error.

Rob

Hi Rob

I’m not criticising your module, I’m just saying that’s what I use to read/write data. Maybe I should have worded the title of the other thread differently, I see your point, sorry, please feel free to delete it.

I simply pasted the MultipleChoice text file into the same place as the other json files (created by your loadsave.lua) in the sandbox/documents folder. The MultipleChoice.txt file is read with no problems in the simulator as are the json files.

What is confusing me is that the json files created by loadsave can’t be found on the phone, it only works if the json file is created by the code first then saved on the phone, like I explained above. It’s as if they are put in another folder after the code is compiled. I have checked the syntax multiple times to make sure there are no typing errors, it’s happening with every file I want to read.

When I run the simulator and open the project sandbox there is a folder called documents, inside that folder are the json files, is this correct?

When you deploy an app to a device, it does not take your Corona Simulator sandbox with you.  Your .apk or app bundle (for iOS) only contains your system.ResourceDirectory folder (where your main.lua is).  When the app starts up on the device, it creates an empty system.DocumentsDirectory and system.TemporaryDirectory (and system.CachesDirectory on iOS).   You cannot pre-populate  system.DocumentsDirectory. 

The loadsave functions can read and write any folder, but it can’t read files that don’t exist.  If you try to use io.open() to read a file that doesn’t exist, you’re going to get that error.  Keep in mind system.ResourceDirectory is read only.  What you have to do, if you plan to write to your .txt file is copy it by reading it from system.ResourceDirectory and write it out to system.DocumentsDirectory then you can start using the file. 

Now are you also saying that loadsave isn’t able to read a file after you save it?  I tested it on my Android Nexus 7 and it works.  Make sure to try the main.lua sample app I included in the github repository.  Also, you cannot see the files on the device like you can on your computer.

Thanks Rob

I deleted the other thread, my questions are getting answered here.

You’ve explained what I didn’t know about the sandbox not being included in the apk, now it makes sense why my files can’t be read.

I’m curious as to why there is a sandbox if it is not used in the final build?

Are my databases secure in the system.ResourceDirectory folder? I wouldn’t want people stealing thousands of multiple choice questions that took me years to make.

Should I copy my databases in main.lua, write them to another more secure directory and then delete them from the resource directory when the app starts first time round? It’s just something that sprang to mind when I read your explanation.

Thanks again.

The sandbox rules are put in place by Apple and Android.  They are read only to prevent people from writing to your app.  If writable folders were included in the app bundles, then it wouldn’t be as secure.

As for protecting your data, you can encrypt the files but that’s about the limit of the protections. 

There really isn’t a more secure location to put your files in that your resource directory.

Hi Rob

I understand what you explained about only the system.ResourceDirectory folder being included in the apk so I moved my json files there.

Here’s where I get stumped again, excuse my ignorance.

I use this code:

local gameData = {}
    local gameData = loadsave.loadTable(“gamedata.json”, system.ResourceDirectory)
    loadsave.saveTable(gameData, “gamedata.json”, system.DocumentsDirectory)

The problem is that your loadsave module doesn’t allow the location system.ResourceDirectory so how am I supposed to load the json file that’s included in my apk?

I’m so confused.

I use a modified version of this code, where I can save/load files on the device.

http://code.coronalabs.com/code/preference-library-save-data-files-tables-numbers-strings-and-boolean

hello! thank you very much yosu! I solved the problem by removing the json from the loadsave.lua file, instead what I did was to create an string function to handle the vars from the table and it’s working perfectly good in the device.

Thank you! (y) have nice coding! :slight_smile:

Jimmy

I am having the exact same issue you had, can you please post exactly how you modified the loadsave.lua code, also if you modified your main code too? I would be extreemly grateful for your help. :slight_smile:

What errors are you getting?  Please look at the console log and not just the popup alert.  There should be more information in your console log.  If you don’t know how to look at your logs, please read:  http://coronalabs.com/blog/2013/07/09/tutorial-basic-debugging/

This code is pretty straight forward and you should not need to modify it.  It defaults to system.DocumentsDirectory already.  As far as android permissions, I don’t know that you need any special permissions for this.

Rob

Hi Rob

I saw your post on another thread and followed your advice in checking if the files exists and if it doesn’t create one:

playerData = loadsave.loadTable(“players.json”)
    if playerData == nil then
        playerData = {}
        playerScore = {}
        playerScore[1]=56300
        playerScore[2]=48660
        playerScore[3]=43900
        playerScore[4]=35100
        playerScore[5]=32400
        playerScore[6]=29500
        playerScore[7]=28700
        playerScore[8]=14300
        playerScore[9]=8200
        playerScore[10]=3900
        playerData.playerScore=playerScore
        storedPlayers = {}
        storedPlayers[1]=“Homer Simpson”
        storedPlayers[2]=“Dexter Morgan”
        playerData.storedPlayers=storedPlayers
        playerData.currentPlayer=“Dexter Morgan”
        playerData.numberOfPlayers=2
        playerLevel = {}
        playerLevel[1]=6
        playerLevel[2]=6
        playerLevel[3]=5
        playerLevel[4]=4
        playerLevel[5]=4
        playerLevel[6]=3
        playerLevel[7]=3
        playerLevel[8]=2
        playerLevel[9]=1
        playerLevel[10]=1
        playerData.playerLevel=playerLevel
        playerName = {}
        playerName[1]=“Filius Flitwick”
        playerName[2]=“Septima Vector”
        playerName[3]=“Charity Burbage”
        playerName[4]=“Severus Snape”
        playerName[5]=“Rolanda Hooch”
        playerName[6]=“Horace Slughorn”
        playerName[7]=“Wilhemina Plank”
        playerName[8]=“Pomona Sprout”
        playerName[9]=“Rubeus Hagrid”
        playerName[10]=“Poppy Pomfrey”
        playerData.playerName=playerName
        playerData.playerCount=10
        playerData.new=0
        loadsave.saveTable(playerData, “players.json”)
    end

I removed the players.json file from the sandbox documents folder and sure enough the file was created.

It worked on my phone but later on when a scene required another database I get this error:

06-21 03:44:01.915: I/Corona(15882): Runtime error
06-21 03:44:01.915: I/Corona(15882): …Documents\Corona Projects\Gameshow\loadQuestions.lua:13: attempt to index local ‘_file’ (a nil value)
06-21 03:44:01.915: I/Corona(15882): stack traceback:
06-21 03:44:01.915: I/Corona(15882):     [C]: ?
06-21 03:44:01.915: I/Corona(15882):     …Documents\Corona Projects\Gameshow\loadQuestions.lua:13: in main chunk
06-21 03:44:01.915: I/Corona(15882):     [C]: in function ‘require’
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:797>
06-21 03:44:01.915: I/Corona(15882):     (tail call): ?
06-21 03:44:01.915: I/Corona(15882):     (tail call): ?
06-21 03:44:01.915: I/Corona(15882):     …Documents\Corona Projects\Gameshow\questionRound.lua:54: in function <…Documents\Corona Projects\Gameshow\questionRound.lua:38>
06-21 03:44:01.915: I/Corona(15882):     ?: in function ‘dispatchEvent’
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:1096>
06-21 03:44:01.915: I/Corona(15882):     (tail call): ?
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:466>
06-21 03:44:01.915: I/Corona(15882):     ?: in function <?:218>
06-21 03:44:02.045: I/Corona(15882): Runtime error
06-21 03:44:02.045: I/Corona(15882): stack traceback:
06-21 03:44:02.045: I/Corona(15882):     [C]: ?
06-21 03:44:02.045: I/Corona(15882):     …Documents\Corona Projects\Gameshow\loadQuestions.lua:13: in main chunk
06-21 03:44:02.045: I/Corona(15882):     [C]: in function ‘require’
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:797>
06-21 03:44:02.045: I/Corona(15882):     (tail call): ?
06-21 03:44:02.045: I/Corona(15882):     (tail call): ?
06-21 03:44:02.045: I/Corona(15882):     …Documents\Corona Projects\Gameshow\questionRound.lua:54: in function <…Documents\Corona Projects\Gameshow\questionRound.lua:38>
06-21 03:44:02.045: I/Corona(15882):     ?: in function ‘dispatchEvent’
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:1096>
06-21 03:44:02.045: I/Corona(15882):     (tail call): ?
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:466>
06-21 03:44:02.045: I/Corona(15882):     ?: in function <?:218>
 

The error relates to my loadQuestions.lua module which only needs to read a text file, here’s the code:

local questions = {}

local _path = system.pathForFile( “MultipleChoice.txt”, system.DocumentsDirectory )
local _file = io.open( _path, “r” )
local counter = 1
local c=1
local question = {}
local ans_1 = {}
local ans_2 = {}
local ans_3 = {}
local ans_4 = {}

for line in _file:lines() do
   
    if counter == 1 then
      question[c] = line

      elseif counter == 2 then
      ans_1[c] = line

      elseif counter == 3 then
      ans_2[c] = line

      elseif counter == 4 then
      ans_3[c] = line

      elseif counter == 5 then
      ans_4[c] = line

   end

   counter = counter + 1

   if counter == 6 then
      counter = 1;
      c=c+1
   end

questions.c = c

end

questions.question = question
questions.ans_1 = ans_1
questions.ans_2 = ans_2
questions.ans_3 = ans_3
questions.ans_4 = ans_4

io.close( _file )
_file = nil
counter = nil
line = nil

   return questions

I’ve checked the spelling, why is my phone not finding the MultipleChoice.txt ? :huh:

This has nothing to do with my loadsave module.  I have to ask, is your MultipleChoice.txt in your system.DocumentsDirectory?  If so how does it get there?  The file doesn’t exist which is why you’re getting this error.

Rob

Hi Rob

I’m not criticising your module, I’m just saying that’s what I use to read/write data. Maybe I should have worded the title of the other thread differently, I see your point, sorry, please feel free to delete it.

I simply pasted the MultipleChoice text file into the same place as the other json files (created by your loadsave.lua) in the sandbox/documents folder. The MultipleChoice.txt file is read with no problems in the simulator as are the json files.

What is confusing me is that the json files created by loadsave can’t be found on the phone, it only works if the json file is created by the code first then saved on the phone, like I explained above. It’s as if they are put in another folder after the code is compiled. I have checked the syntax multiple times to make sure there are no typing errors, it’s happening with every file I want to read.

When I run the simulator and open the project sandbox there is a folder called documents, inside that folder are the json files, is this correct?

When you deploy an app to a device, it does not take your Corona Simulator sandbox with you.  Your .apk or app bundle (for iOS) only contains your system.ResourceDirectory folder (where your main.lua is).  When the app starts up on the device, it creates an empty system.DocumentsDirectory and system.TemporaryDirectory (and system.CachesDirectory on iOS).   You cannot pre-populate  system.DocumentsDirectory. 

The loadsave functions can read and write any folder, but it can’t read files that don’t exist.  If you try to use io.open() to read a file that doesn’t exist, you’re going to get that error.  Keep in mind system.ResourceDirectory is read only.  What you have to do, if you plan to write to your .txt file is copy it by reading it from system.ResourceDirectory and write it out to system.DocumentsDirectory then you can start using the file. 

Now are you also saying that loadsave isn’t able to read a file after you save it?  I tested it on my Android Nexus 7 and it works.  Make sure to try the main.lua sample app I included in the github repository.  Also, you cannot see the files on the device like you can on your computer.