How to Load and Save Data with Corona SDK

In today’s post, we are going to learn how to load and save data with Corona SDK. This is an important lesson because you’ll want to save the player’s coins, level, status and more. Or, you might want to offer in-app purchases and if you do, you’ll need a way to save who bought what. Let’s get started!

If you would like to sign up for our email newsletter to get notified when a new tutorial is posted or other news, please fill out the form on the right. You’ll just need to enter your name and email address. Thanks!

As a quick overview, this app will display the user’s level and a button to increment the level. Every time the button is pressed, the user’s level will be increased by 1.

To start, create new file in your project folder titled main.lua. In this file, we’ll want to require storyboard, json, and hide the status bar. We’ll be using storyboard to manage our scene, json to save our data (don’t know what JSON is? read about it here), and we’ll hide the status bar.

-- Requires storyboard and json
local storyboard = require "storyboard"
json = require('json')

-- hide the status bar
display.setStatusBar( display.HiddenStatusBar )

Next, we’ll want to write our save function. This function accepts two parameters into the function and saves them to a file that we specify. Later, I’ll show you how to use this function.

Note: This function is a global function and will be accessible throughout your app. Local vs. global is out the scope of this tutorial.

-- Save specified value to specified encrypted file
function saveValue(strFilename, strValue)

  local theFile = strFilename
  local theValue = strValue
  local path = system.pathForFile( theFile, system.DocumentsDirectory )

  local file = path, "w+" )
  if file then -- If the file exists, then continue. Another way to read this line is 'if file == true then'.
    file:write(theValue) -- This line will write the contents of the table to the .json file.
    io.close(file) -- After we are done with the file, we close the file.
    return true -- If everything was successful, then return true

Want to know when more tutorials and That’s So Panda news comes out?
Sign up for our mailing list to find out the latest news. Don’t worry, I hate spam as much as you do.

If we have a way to save data, we need a way to load it too! The function below will load values from a file name.

-- Load specified encrypted file, or create new file if it does not exist
function loadValue(strFilename)
  local theFile = strFilename
  local path = system.pathForFile( theFile, system.DocumentsDirectory )
  local file = path, "r" )

  if file then -- If file exists, continue. Another way to read this line is 'if file == true then'.
    local contents = file:read( "*a" ) -- read all contents of file into a string
    io.close( file ) -- Since we are done with the file, close it.
    return contents -- Return the table with the JSON contents
    return '' -- Return nothing

Now that we can save and load data, let’s try to load up a file. That file’s content will be stored in the variable table and the variable is a global variable.

user = json.decode(loadValue('user.txt'))

If the file doesn’t exist, that means the user is using your app for the first time or the text file disappeared for another reason. If this happened, then we’ll want to create a new text file for our user and pre-load it with some information. In our example, we are giving our user 5 coins and assigning them to level 1.

if not user then
  _G.user = {
    coins = 5, -- stores total number of coins
    level = 1, -- stores user level
  saveValue('user.txt', json.encode(user))

Finally, we’ll want to switch the menu scene from the main.lua file.

storyboard.gotoScene( "menu" )

After we’ve finished our main.lua file, we’ll want to create a new menu.lua file in our project folder. We’ll start this new file by requiring storyboard, widget and creating a new scene.

local storyboard = require( "storyboard" )
local scene = storyboard.newScene()
local widget = require("widget")

Next, we’ll create a new function called scene:createScene(event) and create a new text object that will display the the user’s level. For our example, the text object will be updated every time the button is pressed so we can see what’s happening in our app.

function scene:createScene( event )
local group = self.view

local mylevel = display.newText(group, "Level "..user.level,0,0,_FONT,32)
mylevel.x = 160
mylevel.y = 180

After our level, we need to create a function that handles our button tap event. This function will increase the user’s level by 1, save the data, reload it, and then update the on-screen text.

-- Function to handle button events
local function handleButtonEvent( event )
  if ( "ended" == event.phase ) then
    -- increase level by 1
    user.level = user.level + 1

    -- save data
    saveValue('user.txt', json.encode(user))

    -- reload data, not necessary to do it here, but I like too
    user = json.decode(loadValue('user.txt'))

    -- update on screen text
    mylevel.text = "Level "..user.level


Then, we’ll create the button using Corona’s widget library so we have something to press to increment the levels by 1.

-- Create the widget
local button1 = widget.newButton {
left = 60,
top = 240,
id = "button1",
label = "Press me to update level",
onEvent = handleButtonEvent

And we’ll wrap up by creating an event listener for our scene and returning the scene.

scene:addEventListener( "createScene", scene )
return scene

And that’s it to saving and loading data using Corona SDK! There are plenty of ways to save user information in your app and this is just one of them. For learning purposes, I’ve tried to simplify the functions to make it easier to digest.

Thanks for reading! If you have questions or comments, please leave them below and don’t forget to sign up for the newsletter!

  1. Thanks for the tutorial, really helpfull! Pandastic I would say haha!

  2. Thanks for the information!

    I have one problem. I’m making a time, with minute and second.

    I could smoothly save my user.minute and load them back, but when i try doing it with user.second, it fails. it seems like this piece of code only allow me to save one specific thing instead of many?



    • Hello Ming, without seeing your code and how you are pulling the information, my guess is that user.second may not be available from where you are trying to pull it.

Leave a Reply