This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
mrpaluza's profile picture

[LUA] Problems with the fs API

Started by mrpaluza, 06 January 2013 - 07:07 PM
mrpaluza #1
Posted 06 January 2013 - 08:07 PM
I've been messing around with the fs API to store and load variables from files and I've mucked around enough to store strings, and it works because I can open them from an external text editor like Notepad++. I can store strings into a file and read from the same file in the same program, but after reboots the file still holds the same string but when read it prints a blank.

Specifically, this program takes the "var" file and prints its contents and asks for a new var to be stored. It stores, but does not read. It just spews garbage.

local fileWrite = fs.open("testVar", "w")
local fileRead = fs.open("testVar", "r")
if fileRead then
  local read = fileRead.readLine()
  fileRead.close()
end
print(read) 
fileWrite.write(read())
fileWrite.close()

When I replace "readLine" with "readAll" it just prints a blank.

Can anyone help me?
Kingdaro #2
Posted 06 January 2013 - 08:29 PM
Remove the "local" on line 4.

ACTUALLY YOU SHOULDN'T DO THAT UH

Just remove the local and rename that variable to something else.
remiX #3
Posted 07 January 2013 - 12:28 AM
You're opening it twice in a row, since when can you do that? :o/>

You're making read the value of 'fileRead.readLine() ' which will overwrite the read() function. And then you try call the read() function later on
mrpaluza #4
Posted 07 January 2013 - 12:35 PM
Alright so I forget that overlapping variables and functions do some pretty bad things, so Ifixed that, and did this:

local fileWrite = fs.open("testVar", "w")
local fileRead = fs.open("testVar", "r")
if fileRead then
  loadTestVarFile = fileRead.readAll()
  fileRead.close()
end
print(tostring(loadTestVarFile)) 
fileWrite.write(read())
fileWrite.close()
Using fileRead.readLine() returns a nil,
whereas this returns a blank, which I assume is better?

And, sorry, I can't really understand something if it isn't explained, i.e. the local to global fix. Can someone please explain this to me like I'm five. Give me lollipops and sunshine.

Oh, I did see the wiki, and it says that the fileRead.readLine() reads the next line, and fileRead.readAll() reads the rest of the lines. Is this a factor?
Kingdaro #5
Posted 07 January 2013 - 12:45 PM
You already had the file "testVar" opened in writing mode, you can't open it in reading mode again while it's still open.
mrpaluza #6
Posted 07 January 2013 - 01:11 PM
So when I define this:

local fileWrite = fs.open("testVar", "w")
local fileRead = fs.open("testVar", "r")
It opens the files in their respective modes?
So that becomes:

local fileWrite = fs.open("testVar", "w")
fileWrite.close()
local fileRead = fs.open("testVar", "r")
fileRead.close()
this?
Lyqyd #7
Posted 07 January 2013 - 01:13 PM
Yes, though given your test example above, you'd obviously want to be opening the handle for writing after you close the read-mode handle.
mrpaluza #8
Posted 07 January 2013 - 01:16 PM
So this would be correct?

local fileWrite = fs.open("testVar", "w")
fileWrite.close()
local fileRead = fs.open("testVar", "r")
if fileRead then
  local loadVarFromFile = fileRead.readLine()
  fileRead.close()
end
print(tostring(loadVarFromFile))
fileWrite.write(read())
fileWrite.close()

Edit: Oh I see what you mean…

local fileWrite = fs.open("testVar", "w")
local fileRead = fs.open("testVar", "r")
fileRead -- does the above command that opens the file for reading
local loadVarFromFile = fileRead.readLine()
fileRead.close() -- closes the file or handle
print(tostring(loadVarFromFile))
fileWrite -- opens the file for writing
fileWrite.write(read())
fileWrite.close() -- closes the file or handle

Edit 2: Okay, so I was almost fed up with it until I decided to split the read and write into two different programs:

local fileRead = fs.open("testVar", "r")
loadTestVarFile = fileRead.readAll()
fileRead.close()
print(tostring(loadTestVarFile))
This works (finally) and I can see because the file is opened and printed correctly!
Tell me if I am right:
Line one assigns the handle AND opens the handle at the same time.
Line two assigns a local variable as the contents of all the file.
Line three closes the handle.
Line four prints the variable.

Alright! I got it to work, thanks for all the help guys!

local fileRead = fs.open("testVar", "r")
loadTestVarFile = fileRead.readAll()
fileRead.close()
print(tostring(loadTestVarFile))
local fileWrite = fs.open("testVar", "w")
fileWrite.write(read())
fileWrite.close()
Still, I would really appreciate it if someone would tell me if [[local fileRead = fs.open("testVar", "r")]] and [[local fileWrite = fs.open("testVar", "w")]] opens AND assigns the handle at the same time.
NeverCast #9
Posted 07 January 2013 - 01:44 PM
yes it does, it opens and assigns the handle, the handle is actually just a table.

When you go

local handle = fs.open("filename", "r")

The call to fs.open, opens the file by name in the mode you specify, and returns a table as a handle for that file.
You then call functions stored in that table.

Something I should mention is that you should not let loadTestVarFile be global, put a local in front of it.
Here's some helpful code for you.


fs.readAll = function(filename)
  local h = fs.open(filename, "r")
  if h == nil return nil end
  local result = h.readAll()
  h.close()
  return result
end

fs.writeAll = function(filename, content)
  local h = fs.open(filename, "w")
  if h == nil then return false end
  h.write(content)
  h.close()
  return true
end

local content = fs.readAll("testVar")
print(content)
fs.writeAll("testVar", content)

not tested this code but I can't see any issues with it, let me know otherwise
mrpaluza #10
Posted 07 January 2013 - 01:50 PM
But this directly contradicts reply number two, as it says remove the local, or am I just reading that wrong?
NeverCast #11
Posted 07 January 2013 - 02:04 PM
You had to remove that local because it was declared in the scope of the if statement, meaning only code inside the if statement would be able to access it, had it been declared outside of the if and just assigned inside it, there wouldn't have been any issues.

Unless you are writing an API and need to expose some variables or functions, local everything. Every function you make, if the variable isn't needed outside of that function, make it local. Same with loops and if statements, if you declare a temp variable, make it local temp. This prevents a temp variable later on picking up that value.

Declaring a variable is just going

local varName

or
local varName = nil

This makes sure that the variable is declared where you need it, but it isn't global, so it wont mess up other things.

Heck, make functions local too!
if you have two functions in two bits of code, both called.. log! for example, for writing out some information, and one function goes to one file, the other writes to another file. When they're both declared globally ( without a local ), the last one executed will overwrite the first one. How much havoc could that cause?

When you get in to coroutines, you'll see how important scope is.
mrpaluza #12
Posted 07 January 2013 - 02:27 PM
Ah ok, thanks, that really cleared it up, I always thought defining local meant strictly for that program, didn't know it went deep into loops and logic statements.
NeverCast #13
Posted 07 January 2013 - 02:42 PM
If you're after some late night reading, a Scope Tutorial might further your knowledge.
http://lua-users.org/wiki/ScopeTutorial

Feel free to come back here if something is not clear.