Why can't I save what's read from the file to a variable?

So i’m trying to read a number in a file and then save that number to a variable. I’m doing this through a module. When i do this locally it works. If through a module then it doesn’t. 

Here is how i do it locally. 

 local number \_path = system.pathForFile( "digit.txt", system.DocumentsDirectory ) \_file = io.open( \_path, "r" ) for line in \_file:lines() do number = tonumber(line) end io.close( \_file ) \_file = nil \_path = nil print(number)

This works and prints this number in that file. 

Now below i will have the module way. { NOTE - I did require everything correctly and all } 

mod.lua – 

function M.readFile( \_fileName, \_number ) local \_number \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) \_file = io.open( \_path, "r" ) for line in \_file:lines() do \_number = tonumber(line) end io.close( \_file ) \_file = nil \_path = nil end

readIt.lua – 

 local number Z.readFile( "digit.txt", number ) print(number)

So why isn’t it adding the number to “local number”? It just prints “nil”.

Thanks!

–SonicX278 

Lua passes tables/objects  by reference.  

All other types are pass-by-value.  

What is number?  You seem to treat it like a non-table value, but the you use the read function like it’s a table.  I’m confused.  Are you

  • reading a bunch of lines from the file and wanting them all
  • reading a single line and wanting it
  • reading all the lines in a file, but only wanting the last (which is what your code looks like

Anyways, assuming you want the last line in the file and assuming it is a number, try this:

function M.readFile( \_fileName) local \_number local \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) local \_file = io.open( \_path, "r" ) for line in \_file:lines() do \_number = tonumber(line) end io.close( \_file ) return \_number end

local number = Z.readFile( "digit.txt" ) print(number)

If you have a file of numbers and want them all do this:

function M.readFile( \_fileName, numberTable ) local \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) local \_file = io.open( \_path, "r" ) for line in \_file:lines() do numberTable[#numberTable+1] = tonumber(line) end io.close( \_file ) end

local numbers = {} Z.readFile( "digit.txt", numbers ) for i = 1, #number do print(numbers[i]) end

There’s only one number in a file. So there’s only one line. Now iv’e tried your first method before and that didn’t work.

First method return nil.

Second method gives an error. But i don’t need a table so scratch that method?

What’s confusing is the number is being written to the file perfectly. 

Any other suggestions?

Maybe there’s a different way to read a number from a file and give it to a variable?

–SonicX278 

My suggestion as always is NOT to write these utilities yourself.  

I provide all the basic file, table, etc. utilities in SSK:

http://github.com/roaminggamer/SSKCorona

If you don’t want all of SSK you can grab the extensions from this example:

http://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2016/03/ssk_core.zip

--From example: io.writeFile( 10, "myNumber.txt" ) local tmp = tonumber( io.readFile( "myNumber.txt") ) print( tmp ) tmp = tmp + 10 io.writeFile( tmp, "myNumber.txt" ) local tmp = tonumber( io.readFile( "myNumber.txt") ) print( tmp )

At the very least  you can see what I wrote to learn how it works… these functions have been used thousands of times by myself and many others.

Yes i can use your SSK but i wont have that feeling of accomplishment and will still want to get it working haha. So you don’t know another way i can fix it and get it working? I think ill have to reading docs and forums. Maybe i can find something.

–SonicX278

Yes, read my code, see how it works, see it working, experiment, learn.

http://github.com/roaminggamer/RG_FreeStuff/blob/master/AskEd/2016/03/ssk_core/ssk_core/extensions/io.lua

if( io.readFile ) then print("ERROR! io.readFile() exists already") else function io.readFile( fileName, base ) local base = base or system.DocumentsDirectory local fileContents if( io.exists( fileName, base ) == false ) then return nil end local fileName = fileName if( base ) then fileName = system.pathForFile( fileName, base ) end local f=io.open(fileName,"r") if (f == nil) then return nil end fileContents = f:read( "\*a" ) io.close(f) return fileContents end end if( io.writeFile ) then print("ERROR! io.writeFile() exists already") else function io.writeFile( dataToWrite, fileName, base ) local base = base or system.DocumentsDirectory local fileName = fileName if( base ) then fileName = system.pathForFile( fileName, base ) end local f=io.open(fileName,"w") if (f == nil) then return nil end f:write( dataToWrite ) io.close(f) end end

Sorry, but I gave you an alternate solution above and you rejected it as, “I tried that and it didn’t work…”.  So, the only alternative is for me to show you a working example which I’ve done.  

Unfortunately, I don’t have the time right now to take your code, run in locally, debug it, and give it back to you fixed, which I guess is the third option… :unsure:  

@SonicX278
Inside your M.readFile you are setting _number as a local variable. This replaces the _number parameter you are passing when you call the function and you loose the reference.

But _number is neither a table nor a function: it’s a value, as correctly noted by @roaminggamer so i think you’d do better by returning the value from the M.readFile instead of passing it’s reference as a parameter

I totally get wanting to learn and accomplish things, but at the same time you have to ask, “What is my goal here, learning or making a game?”

If it is learning, then that is awesome.  However, you can still learn by starting with a working base and tweaking till you break it or understand how it works.

@RoamingGamer – I have to head off to church soon so ill take a hard look at the ssk after.

@g.sciacchitano – Did you mean something like this?

function M.readFile( \_fileName, \_number ) \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) \_file = io.open( \_path, "r" ) for line in \_file:lines() do \_number = tonumber(line) end io.close( \_file ) return \_number end

 local number NumberZ.readFile( "playerScore.txt", number ) print(number)

–SonicX278

@sonic,

No that is wrong.  He noticed you were creating a local which overwrote _number, but you still can’t pass in _number as a reference.  It isn’t a table or object.

Listen, if you really want to learn this stuff focus on LUA then Corona.  Grab the PIL, read it, write the examples, you’ll learn that way for sure:

http://www.lua.org/pil/

Also, grab Brian’s book(s) and follow them to learn more:

http://www.burtonsmediagroup.com/books/

I ended up doing this. It works now. 

function M.readFile( \_fileName ) \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) \_file = io.open( \_path, "r" ) for line in \_file:lines() do \_number = tonumber(line) end io.close( \_file ) \_file = nil \_path = nil return \_number end

 local number = NumberZ.readFile( "playerScore.txt" ) print(number)

I removed the the local variable from the readFile function and added “return _number”.

Hmm. Weird. @RoamingGamer – Your first method ended up working. But only after i removed the “local _number” from it and testing it and it worked. Then i added it in again and it ended working. 

Thanks @RoamingGamer!

–SonicX278 

Also its not that i didn’t understand how this works and how to do it. It wasn’t working until i restarted my simulator. ( I have my PC on for weeks at a time and usually on a load )

Which results in my sim nitnworkkmg properly sometimes.

–SonicX278

Hey.  I noticed you didn’t take my advice from the other post/thread re: nil-ing  and that there is a coding issue that could bite you later if you continue to do it.  You make some globals then nil them.   

This is better and more correct:

function M.readFile( \_fileName ) local \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) local \_file = io.open( \_path, "r" ) local \_number for line in \_file:lines() do \_number = tonumber(line) end io.close( \_file ) return \_number end

So removing the nil’s and adding the _number variable will be a better practice of doing this?

–SonicX278

Not creating globals for what is essentially local work, and using locals is a better practice, “Yes.”

Note: The locals fall out of scope at the end of the function and don’t need to be nil’d.

Understood. Thanks!

–SonicX278

Lua passes tables/objects  by reference.  

All other types are pass-by-value.  

What is number?  You seem to treat it like a non-table value, but the you use the read function like it’s a table.  I’m confused.  Are you

  • reading a bunch of lines from the file and wanting them all
  • reading a single line and wanting it
  • reading all the lines in a file, but only wanting the last (which is what your code looks like

Anyways, assuming you want the last line in the file and assuming it is a number, try this:

function M.readFile( \_fileName) local \_number local \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) local \_file = io.open( \_path, "r" ) for line in \_file:lines() do \_number = tonumber(line) end io.close( \_file ) return \_number end

local number = Z.readFile( "digit.txt" ) print(number)

If you have a file of numbers and want them all do this:

function M.readFile( \_fileName, numberTable ) local \_path = system.pathForFile( \_fileName, system.DocumentsDirectory ) local \_file = io.open( \_path, "r" ) for line in \_file:lines() do numberTable[#numberTable+1] = tonumber(line) end io.close( \_file ) end

local numbers = {} Z.readFile( "digit.txt", numbers ) for i = 1, #number do print(numbers[i]) end

There’s only one number in a file. So there’s only one line. Now iv’e tried your first method before and that didn’t work.

First method return nil.

Second method gives an error. But i don’t need a table so scratch that method?

What’s confusing is the number is being written to the file perfectly. 

Any other suggestions?

Maybe there’s a different way to read a number from a file and give it to a variable?

–SonicX278 

My suggestion as always is NOT to write these utilities yourself.  

I provide all the basic file, table, etc. utilities in SSK:

http://github.com/roaminggamer/SSKCorona

If you don’t want all of SSK you can grab the extensions from this example:

http://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2016/03/ssk_core.zip

--From example: io.writeFile( 10, "myNumber.txt" ) local tmp = tonumber( io.readFile( "myNumber.txt") ) print( tmp ) tmp = tmp + 10 io.writeFile( tmp, "myNumber.txt" ) local tmp = tonumber( io.readFile( "myNumber.txt") ) print( tmp )

At the very least  you can see what I wrote to learn how it works… these functions have been used thousands of times by myself and many others.

Yes i can use your SSK but i wont have that feeling of accomplishment and will still want to get it working haha. So you don’t know another way i can fix it and get it working? I think ill have to reading docs and forums. Maybe i can find something.

–SonicX278