Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

File error when trying to save data using JSON
Started by XeduR @Spyric Jan 06 2019 09:49 AM

- - - - -
13 replies to this topic
json loadsave file error

Best Answer SGS , 16 January 2019 - 04:50 PM

I don't get why you need to open the file and then open it again in the save block? My code worked perfectly every time without this extra (and seemingly pointless) step.

You might have more luck if you close the file after the first open and before the second open.

-- if the file is loaded, then we run into issues
if file then
	saveData = loadTable( "data.json" )
        io.close(file)   <-- close before opening it later!
end

I imagine, because you haven't closed the file after the first read it remains locked for some OS specific time.

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

I had encountered this issue with my own code, so this time I "borrowed" the loadsave code from Corona's documentation in order to make sure it wasn't just my code.

When I first start the app on simulator (or start it after having wiped the project's sandbox), there are no issues. I create and save a table called "data" as JSON.

The problems arise when I start the app again and the data.json file exists in the project's Documents directory. The table is loaded correctly, but if I try to save it again immediately, then I am met with the following error message: "File error: C:\....\Documents\data.json: Permission denied". According to the loadsave.lua file's M.saveTable function, the file simply does not exist. However, if I try to save the table after a long delay by using timer.performWithDelay, like 15-20s, then the file does exist and everything works.

What is specifically the cause of this issue and how could I address it?

I have attached a sample project that demonstrates the issue. Just comment the rows 27 and 29 in main.lua to toggle between instant and delayed saving.

Attached Files



[TOPIC: post.html]
#2

agramonte

[GLOBAL: userInfoPane.html]
agramonte
  • Corona Geek

  • 1,009 posts
  • Corona SDK

I don't have a PC but on my Mac and my android device, your code works as expected. No error. No delay needed.

 

That being said in general I wait until the system responds back that it is ready before I do any file operations. Not sure if this will fix your issue since I am not on a PC and couldn't replicate your issue.

local function systemEvents( event )
	delayedSave()
end
  
Runtime:addEventListener( "system", systemEvents )



[TOPIC: post.html]
#3

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,372 posts
  • Enterprise

This sounds like an odd Windows caching issue. Perhaps Windows is holding on to a file handle too long, or a buffer hasn't flushed yet. What do you need to write that immediately?

 

Rob



[TOPIC: post.html]
#4

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

Thanks for the replies.

On the first start up, I create and save a table for the general options and other variables as soon as the app starts, and this works without a hitch.

 

On future restarts, it isn't that I am trying to write something immediately, but that some times it can take up to 14s until I can save the JSON file without encountering an error. In those 14s, I can go to the app's options, change the app's language, turn off music, etc. or maybe go to some level, perform some actions and still have time to spare. If I then close the app, all of those options should have been saved the moment that I made them. However, upon restart, I find that the changes weren't saved and the console log keeps showing me the same error message every time I tried to save.

 

Once that varying time window since the app's start has passed, I can save as frequently as I want without any errors.



[TOPIC: post.html]
#5

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,963 posts
  • Corona SDK

I save some 500KB locally and never had this issue.  Have you got some anti virus/malware scanner that is locking the file maybe?



[TOPIC: post.html]
#6

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

Seems like I need to be doing some testing with antivirus and related software then. Good to know that it is localised to my computer. 



[TOPIC: post.html]
#7

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

I've been trying to figure this one out for a while now and I've tried disabling all sorts of software that might be interfering, but I am at my wits end.

The duration for the file error also seems to be project specific. I used the following code to highlight the issue:

local function start()
	local count = 1
	local function rapidSave()
		loadsave.saveTable( data, "data.json")
		print("Time:"..math.floor(system.getTimer()),"\tloop #:"..count)
		count = count+1
	end
	timer.performWithDelay( 100, rapidSave, 50 )
end
timer.performWithDelay( 2000, start )

Depending the project, it took anywhere from a few seconds to almost 20 seconds until the saving actually went through. And like before, once it goes through, then it just keeps on going without any interference. Here's a few seconds long clip of the console log with the following code in a project of mine (https://gfycat.com/ImmenseWavyBrahmanbull). The console is barraged with errors, until everything just starts to work.

I would really appreciate it if anyone had a clue as to what is going on.

 



[TOPIC: post.html]
#8

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,963 posts
  • Corona SDK

can you try this?

local json = require "json"
local data = {1,2,3,4,5,6,7,8,9,10}

local function saveTable( dataTable, filename )
  local myTable = json.encode( dataTable )
  local path = system.pathForFile( filename, system.DocumentsDirectory )
  local file = io.open( path, "w" )
  if file then
    file:write( myTable )
    io.close( file )
  else print("error") end
end

local function start()
  local count = 1
  local function rapidSave()
    local start = system.getTimer()
    saveTable( data, "data.json")
    print("Save in "..math.floor(system.getTimer() - start).."ms", "\tloop #:"..count)
    count = count + 1
  end
  timer.performWithDelay( 100, rapidSave, 50 )
end
timer.performWithDelay( 2000, start )

output for me is

15:51:07.423  Project sandbox folder: C:\Users\AppData\Local\Corona Labs\Corona Simulator\Sandbox\5A44ECC91411385BE32625F1BF14938E\Documents
15:51:09.556  Save in 2ms		loop #:1
15:51:09.650  Save in 0ms		loop #:2
15:51:09.775  Save in 2ms		loop #:3
15:51:09.858  Save in 1ms		loop #:4
15:51:09.952  Save in 1ms		loop #:5
15:51:10.075  Save in 1ms		loop #:6
15:51:10.148  Save in 2ms		loop #:7
15:51:10.274  Save in 1ms		loop #:8
15:51:10.378  Save in 2ms		loop #:9
15:51:10.481  Save in 1ms		loop #:10

  • XeduR @Spyric likes this

[TOPIC: post.html]
#9

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

I tried it and I received no errors. I even tried again and included the errorString which also stated that there were no errors at any point.

EDIT: Well, I received no errors as I didn't try to load the file first (if it exists) and then try to save it afterwards. The issue still exists, as is demonstrated by the code below in my new post.



[TOPIC: post.html]
#10

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,963 posts
  • Corona SDK

No idea, I've not looked at your project.

 

I just gave you the most simple saving code I could think of for you to test.



[TOPIC: post.html]
#11

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

Well, simple is usually the best, but it seems that I jumped the gun here.

The same problem as before still occur if I first check if the file exists and then load the file. Here's the revised code:
 

local json = require "json"
local data = {1,2,3,4,5,6,7,8,9,10}

local function saveTable( dataTable, filename )
  local myTable = json.encode( dataTable )
  local path = system.pathForFile( filename, system.DocumentsDirectory )
  local file = io.open( path, "w" )
  if file then
    file:write( myTable )
    io.close( file )
  else print("error") end
end

local function loadTable( filename )
  local path = system.pathForFile( filename, system.DocumentsDirectory )
  local file = io.open( path, "w" )
  if file then
    local contents = file:read( "*a" )
    local t = json.decode( contents )
    io.close( file )
    return t
  else print("error") end
end


local path = system.pathForFile( "data.json", system.DocumentsDirectory )
local file = io.open( path, "r" )
if file then
  saveData = loadTable( "data.json" )
end


local function start()
  local count = 1
  local function rapidSave()
    local start = system.getTimer()
    saveTable( data, "data.json")
    print("Save in "..math.floor(system.getTimer() - start).."ms", "\tloop #:"..count)
    count = count + 1
  end
  timer.performWithDelay( 100, rapidSave, 50 )
end
timer.performWithDelay( 2000, start )


My console output is:
 

18:30:23.238  Project sandbox folder: C:\Users\AppData\Local\Corona Labs\Corona Simulator\Sandbox\json file error-5C54F9E7F7FE5110E495ABFBB7F62136\Documents
18:30:23.249  error
18:30:25.366  error
18:30:25.366  Save in 0ms		loop #:1
18:30:25.459  error
18:30:25.459  Save in 0ms		loop #:2
18:30:25.563  error
18:30:25.563  Save in 0ms		loop #:3
18:30:25.660  error
18:30:25.660  Save in 0ms		loop #:4


[TOPIC: post.html]
#12

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

Well, I've done some extra digging and it seems that other users have had this issue as well in the past, for instance: https://forums.coronalabs.com/topic/59206-unable-to-save-score-between-sessions-error-could-not-read-nil/

I also made a new visual builds for win32 and Mac and asked friends to try them out. Those on a Mac had no issues, but everyone on Windows encountered the same issues as I've described. The first time that they run the project, everything works as expected, but every other start up it takes tens of attempts (official record is now 168 attempts at 100ms delay between attempts) until the save actually goes through.

The issue lies with io.open and seems to only affect Windows. It affects both running the code on simulator as well as building and running as a win32 build.

I would greatly appreciate it if anyone on Windows could confirm if they are also experiencing this issue.

Here is the updated code with visual indicators. I've also attached the project.

local json = require "json"
local data = {1,2,3,4,5,6,7,8,9,10}

local options = {
    text = "",
    x = display.contentCenterX,
    y = display.contentCenterY,
    width = display.actualContentWidth*0.75,
    font = native.systemFont,
    fontSize = 18,
    align = "center"
}
local text = display.newText( options )
text:setFillColor(1,0,0)
local tmr

local function saveTable( dataTable, filename, count )
	local myTable = json.encode( dataTable )
	local path = system.pathForFile( filename, system.DocumentsDirectory )
	local file, errorString = io.open( path, "w" )
	if file then
		timer.cancel( tmr )
		text:setFillColor(0,1,0)
		text.text = filename.." loaded\n\nAttempt #"..count
		file:write( myTable )
		io.close( file )
	else
		text.text = errorString.."\n\nAttempt #"..count
	end
end

local function loadTable( filename )
	local path = system.pathForFile( filename, system.DocumentsDirectory )
	local file = io.open( path, "w" )
	if file then
		local contents = file:read( "*a" )
		local t = json.decode( contents )
		io.close( file )
		return t
	else print("Error when loading file") end
end

local path = system.pathForFile( "data.json", system.DocumentsDirectory )
local file = io.open( path, "r" )

-- if the file is loaded, then we run into issues
if file then
	saveData = loadTable( "data.json" )
end

local count = 1
local function rapidSave()
	saveTable( data, "data.json", count)
	count = count + 1
end
tmr = timer.performWithDelay( 100, rapidSave, 0 )

Attached Files



[TOPIC: post.html]
#13

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 1,963 posts
  • Corona SDK

  Best Answer

I don't get why you need to open the file and then open it again in the save block? My code worked perfectly every time without this extra (and seemingly pointless) step.

You might have more luck if you close the file after the first open and before the second open.

-- if the file is loaded, then we run into issues
if file then
	saveData = loadTable( "data.json" )
        io.close(file)   <-- close before opening it later!
end

I imagine, because you haven't closed the file after the first read it remains locked for some OS specific time.


  • XeduR @Spyric likes this

[TOPIC: post.html]
#14

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 582 posts
  • Corona SDK

I was already about to write a post on how I close the file after loading it on row 38, but after including io.close(file) where you suggested, the saves again went through straight away. There was still an issue with loading the file, but that was literally due to the data.json file having already been opened. Avoiding the double open, which seemingly happened, fixed it.

 

local path = system.pathForFile( "data.json", system.DocumentsDirectory )
local file = io.open( path, "r" )

local saveData

if file then -- not using the loadTable function with additional io.open(file)
	local contents = file:read( "*a" )
	saveData = json.decode( contents )
	io.close( file )
else print("Error when loading file") end

The extra and seemingly pointless step isn't that at all, but it was the reason for my errors. I included it because I want to see if the data.json file exists. It may include save data or general options data which I want to load as the game starts, however, if the user makes any changes, I'd want to save those changes to the file as well. If the file doesn't exist, then a file with default values was created and the double opening of the file didn't occur, which meant that there were no issues.

 

Thank you for taking the time to help me out @SGS. Seems that my projects may have included this issue for years, but I just haven't realised because the loading screens and logos have delayed the apps enough for the OS to close the files by itself.




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: json, loadsave, file error