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

Problem with reading and writing files in code

Started by jeepracer98, 02 June 2012 - 04:48 AM
jeepracer98 #1
Posted 02 June 2012 - 06:48 AM
So, basicly whenever I run my code it works until it hits the
h.write(message)
then it says
startup:33: attempt to index ? (a nil value)
is there some problem in my code?
Thanks in advance.

[left]Full Code:[/left]

-- Functions
function split(str, pat)
   local t = {}  -- NOTE: use {n = 0} in Lua-5.0
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
	  if s ~= 1 or cap ~= "" then
  table.insert(t,cap)
	  end
	  last_end = e+1
	  s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
	  cap = str:sub(last_end)
	  table.insert(t, cap)
   end
   return t
end
-- Real Program
term.clear()
term.setCursorPos(1,1)
rednet.open("top")
print("Interwebby OS v0.03b")
while true do
  event, id, message = os.pullEvent()
  if event == "rednet_message" then
	local time = os.time()
	filename = id .. "|split|" .. time
	h = fs.open(filename, "w")
	h.write(message)
	h.close()  
  end
end
D3matt #2
Posted 02 June 2012 - 06:52 AM
Check if h exists.
PixelToast #3
Posted 02 June 2012 - 06:53 AM
try replacing

h.close()
with:

io.close(h)
PixelToast #4
Posted 02 June 2012 - 06:54 AM
Check if h exists.
read the code, he declared h here:

h = fs.open(filename, "w")
Luanub #5
Posted 02 June 2012 - 06:58 AM
I see a couple of possible issues

This line:

filename = id .. "|split|" .. time

You have some extra spaces and the var time is never declared. Also I think you are intedning to use the function split here? if so it would need to be done something like

filename = split(id)
and you will need to modify the split function to accept arguments


function split(arg1)
jeepracer98 #6
Posted 02 June 2012 - 07:00 AM
I now see that h.write(variable) does not work. Is there any way around this?
jeepracer98 #7
Posted 02 June 2012 - 07:04 AM
I see a couple of possible issues

This line:

filename = id .. "|split|" .. time

You have some extra spaces and the var time is never declared. Also I think you are intedning to use the function split here? if so it would need to be done something like

filename = split(id)
and you will need to modify the split function to accept arguments


function split(arg1)
I was just meaning to write it to a file named <id-variable>|split|<time variable>
I was going to use the split function later to split apart the filename.

try replacing

h.close()
with:

io.close(h)
Would that still work even though I was using fs instead of io?
D3matt #8
Posted 02 June 2012 - 07:06 AM
Check if h exists.
read the code, he declared h here:

h = fs.open(filename, "w")
That doesn't mean h exists. h could be nil if fs.open() failed for some reason (filename was nil or invalid, for example).

h.write(variable) works fine, as long as: h is not nil, and variable is not nil.
jeepracer98 #9
Posted 02 June 2012 - 07:22 AM
what characters are inva
Check if h exists.
read the code, he declared h here:

h = fs.open(filename, "w")
That doesn't mean h exists. h could be nil if fs.open() failed for some reason (filename was nil or invalid, for example).

h.write(variable) works fine, as long as: h is not nil, and variable is not nil.
what characters are invalid? When I go into lua prompt mode and type

lua>f = "foo"
lua>h = fs.open(f, "w")
lua>h.write("hello")
lua>h.close()
it shows "hello" in the file foo. So that works, I believe.
Luanub #10
Posted 02 June 2012 - 07:24 AM
@D3matt - Doing h = fs.open(filename, "w") will create the file if it does not exist. If you check for it and it does not exist that is what you run to create it….


h.close() is also the proper way to close the handle using the fs API.

Try doing this to put together the filename. I don't think the pipes( | ) are valid in a file path so…


filename = (id.."/split/"..time)

just make sure time is declared as I do not see that in your code and you should be good to go.
jeepracer98 #11
Posted 02 June 2012 - 07:27 AM
@D3matt - Doing h = fs.open(filename, "w") will create the file if it does not exist. If you check for it and it does not exist that is what you run to create it….


h.close() is also the proper way to close the handle using the fs API.

Try doing this to put together the filename. I don't think the pipes( | ) are valid in a file path so…


filename = (id.."/split/"..time)

just make sure time is declared as I do not see that in your code and you should be good to go.
I changed the line to

filename = (id.."/split/"..time)
but It still gave me the same error. Should I maybe try using the io api instead? Does that work in the same way?
Luanub #12
Posted 02 June 2012 - 07:33 AM
For the most part, I personally prefer io over fs.

for io:

local h = io.open(filename, "w")
h:write(message)
h:close()

What format is the data in the time var? That might also be causing you problems if its not in an acceptable format or has invalid filename characters in it
jeepracer98 #13
Posted 02 June 2012 - 07:35 AM
Oh, I just got it to work. I changed the

h = fs.open(filename, "w")
to

local h = fs.open(filename, "w")
and "/split/" to "[split]" and it worked. Thanks for all your help! I bet the /'s weren't allowed either.
Thanks again.
Also, how do I add 1 to people's rep on the forum?
thankee,
JR98
Luanub #14
Posted 02 June 2012 - 07:35 AM
Click on the little up arrow above the quote. Glad to help :)/>/>
jeepracer98 #15
Posted 02 June 2012 - 07:36 AM
For the most part, I personally prefer io over fs.

for io:

local h = io.open(filename, "w")
h:write(message)
h:close()

What format is the data in the time var? That might also be causing you problems if its not in an acceptable format or has invalid filename characters in it
I might try io instead later. I believe the time variable is just a string. I am gonna go to sleep cause its around 11:30 pm where I live, but thanks everybody!
D3matt #16
Posted 02 June 2012 - 07:38 AM
@D3matt - Doing h = fs.open(filename, "w") will create the file if it does not exist. If you check for it and it does not exist that is what you run to create it….
Assuming that filename exists and the directory you're trying to create it in (in this case root so that part doesn't matter) also exists, this is true. It's still good practice.
Luanub #17
Posted 02 June 2012 - 07:47 AM
@D3matt - Doing h = fs.open(filename, "w") will create the file if it does not exist. If you check for it and it does not exist that is what you run to create it….
Assuming that filename exists and the directory you're trying to create it in (in this case root so that part doesn't matter) also exists, this is true. It's still good practice.

In this case with the way he has the code written the only nesessary check would be for the directory if he was using sub directories.

Since he is using "w" checking for the file is just adding uneeded lines to the code.

If he was reading the file or appending the file then I agree there needs to be a check and it should be one of the first things in the script. But not in this case..
MysticT #18
Posted 02 June 2012 - 08:35 PM
In this case with the way he has the code written the only nesessary check would be for the directory if he was using sub directories.

Since he is using "w" checking for the file is just adding uneeded lines to the code.

If he was reading the file or appending the file then I agree there needs to be a check and it should be one of the first things in the script. But not in this case..
I would check anyway, there might be some error that doesn't let the file to be created (it's already open, it's a directory, etc.) and it would return nil. My advice: Always check the returned file handles.

Oh, I just got it to work. I changed the

h = fs.open(filename, "w")
to

local h = fs.open(filename, "w")
and "/split/" to "[split]" and it worked. Thanks for all your help! I bet the /'s weren't allowed either.
Thanks again.
Also, how do I add 1 to people's rep on the forum?
thankee,
JR98
The problem when using id.."/split/"..time is that it was trying to create a file named <whatever is in "time"> inside a directory named split, inside a directory named <whatever is in "id">. So for example, if id is "1" and time is "10:30", the path would be "1/split/10:30".
That directory doesn't exist, so it can't create the file in there, that's why it returned nil.