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

bankingServer:49: attempt to call nil

Started by LeviM, 12 January 2015 - 03:52 PM
LeviM #1
Posted 12 January 2015 - 04:52 PM
I have encountered many attempt to call nil errors before but I just can't seem to pinpoint this one.
It calls nil when it is writing some info to a file. Please look at the code linked below.

CODE
SquidDev #2
Posted 12 January 2015 - 05:06 PM
First thing: Use locals. Everywhere.

At line 23 you call:

acFile = fs.open("accounts/"..name,"r")

But then later (line 49) you are trying to write to the same handle. You need to close, then reopen the file in write mode.
Edited on 12 January 2015 - 04:06 PM
MKlegoman357 #3
Posted 12 January 2015 - 05:06 PM
It's because you open that file in read mode. You should open it in write mode if you want to write to it.
Edited on 12 January 2015 - 04:06 PM
InDieTasten #4
Posted 12 January 2015 - 05:16 PM
-deleted-
Edited on 12 January 2015 - 04:16 PM
LeviM #5
Posted 12 January 2015 - 05:34 PM
Thanks all! That solved it! (Kinda, I had to close the reading and open it in write later)
LeviM #6
Posted 12 January 2015 - 08:09 PM
Since it is in the same project I thought I'd post this here.

This code throws a Java exception. It works hand in hand with this code.

EDIT: If it help, I think it fails after it opens the 'to' file for writing but before it actually writes to it.
Edited on 12 January 2015 - 07:11 PM
Lyqyd #7
Posted 12 January 2015 - 10:11 PM
Why do you open the name file for writing, but never write anything to it?
safetyscissors #8
Posted 13 January 2015 - 08:20 AM
Hi LeviM, you've gotten pretty far on that bank program!
Your code thats throwing a java exception has a number of OBO errors.
below are the fixes that make it run correctly.
Spoiler

rednet.open("back")

while true do
	 id,request = rednet.receive()
	 if request == "balance" then
		  id,name = rednet.receive(.5)
		  id,pass = rednet.receive(.5)
		  --#if pass ~= nil or name ~= nil then
		  if pass ~= nil and name ~= nil then
			   --#check if exist
			   if not fs.exists('Accounts/'..name) then return; end
			   local account = fs.open("Accounts/"..name,"r")
			   local accountInfo = {}
			   for line in account.readLine do
					accountInfo[#accountInfo+1] = line
			   end
			   account.close()
			   if accountInfo[1] == pass then
					rednet.send(id,accountInfo[2])
			   end
		  end
	 elseif request == "transfer" then
		  --#got rid of id cause its not being used
		  _,name = rednet.receive(.5)
		  _,pass = rednet.receive(.5)
		  _,to = rednet.receive(.5)
		  _,ammount = rednet.receive(.5)

		  --#if name ~= nil or pass ~= nil or to ~= nil or ammount ~= nil then
		  if name ~= nil and pass ~= nil and to ~= nil and ammount ~= nil then
			   --#check if exist
			   if not fs.exists('Accounts/'..name) then return; end
			   if not fs.exists('Accounts/'..to) then return; end
			   local account = fs.open("Accounts/"..name,"r")
			   local accountInfo = {}
			   for line in account.readLine do
					print(line)
					--#accountInfo[#accountInfo+1] = line  --this one is just preference
					table.insert(accountInfo,line)
			   end
			   account.close()
			   if pass == accountInfo[1] then
					if fs.exists("Accounts/"..to) == true then
						 local tmpPerson = fs.open("Accounts/"..to,"r")
						 local personInfo = {}
						 for line in tmpPerson.readLine do
							  --#personInfo[#personInfo+1] = line  --this one is just preference
							  table.insert(personInfo,line)
						 end
						 tmpPerson.close()
						 if tonumber(accountInfo[2]) >= ammount then
							  personInfo[2] = tonumber(personInfo[2])+ammount
							  print('added '..personInfo[2])
							  local person = fs.open("Accounts/"..to,"w")
							  --#for i=0, #personInfo do --mainly causing the java error i believe
							  for i=1, #personInfo do
								   person.writeLine(personInfo[i])
							  end
							  person.close()
							  local account = fs.open("Accounts/"..name,"w")
							  accountInfo[2] = tonumber(accountInfo[2])-ammount
							  --#for i=0, #accountInfo do --mainly causing the java error i believe
							  for i=1, #accountInfo do
								   --#person.writeLine(accountInfo[i])
								   account.writeLine(accountInfo[i])
							  end
							  account.close()
							  --#person.close() moved higher up
						 end
					end
			   end
		  end
	 end
end
LeviM #9
Posted 13 January 2015 - 04:42 PM
Why do you open the name file for writing, but never write anything to it?
If you look closely I do.
Hi LeviM, you've gotten pretty far on that bank program!
Your code thats throwing a java exception has a number of OBO errors.
below are the fixes that make it run correctly.
Spoiler

rednet.open("back")

while true do
	 id,request = rednet.receive()
	 if request == "balance" then
		  id,name = rednet.receive(.5)
		  id,pass = rednet.receive(.5)
		  --#if pass ~= nil or name ~= nil then
		  if pass ~= nil and name ~= nil then
			   --#check if exist
			   if not fs.exists('Accounts/'..name) then return; end
			   local account = fs.open("Accounts/"..name,"r")
			   local accountInfo = {}
			   for line in account.readLine do
					accountInfo[#accountInfo+1] = line
			   end
			   account.close()
			   if accountInfo[1] == pass then
					rednet.send(id,accountInfo[2])
			   end
		  end
	 elseif request == "transfer" then
		  --#got rid of id cause its not being used
		  _,name = rednet.receive(.5)
		  _,pass = rednet.receive(.5)
		  _,to = rednet.receive(.5)
		  _,ammount = rednet.receive(.5)

		  --#if name ~= nil or pass ~= nil or to ~= nil or ammount ~= nil then
		  if name ~= nil and pass ~= nil and to ~= nil and ammount ~= nil then
			   --#check if exist
			   if not fs.exists('Accounts/'..name) then return; end
			   if not fs.exists('Accounts/'..to) then return; end
			   local account = fs.open("Accounts/"..name,"r")
			   local accountInfo = {}
			   for line in account.readLine do
					print(line)
					--#accountInfo[#accountInfo+1] = line  --this one is just preference
					table.insert(accountInfo,line)
			   end
			   account.close()
			   if pass == accountInfo[1] then
					if fs.exists("Accounts/"..to) == true then
						 local tmpPerson = fs.open("Accounts/"..to,"r")
						 local personInfo = {}
						 for line in tmpPerson.readLine do
							  --#personInfo[#personInfo+1] = line  --this one is just preference
							  table.insert(personInfo,line)
						 end
						 tmpPerson.close()
						 if tonumber(accountInfo[2]) >= ammount then
							  personInfo[2] = tonumber(personInfo[2])+ammount
							  print('added '..personInfo[2])
							  local person = fs.open("Accounts/"..to,"w")
							  --#for i=0, #personInfo do --mainly causing the java error i believe
							  for i=1, #personInfo do
								   person.writeLine(personInfo[i])
							  end
							  person.close()
							  local account = fs.open("Accounts/"..name,"w")
							  accountInfo[2] = tonumber(accountInfo[2])-ammount
							  --#for i=0, #accountInfo do --mainly causing the java error i believe
							  for i=1, #accountInfo do
								   --#person.writeLine(accountInfo[i])
								   account.writeLine(accountInfo[i])
							  end
							  account.close()
							  --#person.close() moved higher up
						 end
					end
			   end
		  end
	 end
end
Thank you! You are a literal genius!
LeviM #10
Posted 13 January 2015 - 08:42 PM
Since I finished it and it works I just thought I'd say something about it. It requires a file server, an account server and a client. Accounts are kept in 'Accounts/[name]'.

The modem side is hard coded in so you will have to change it. You can type 'banking help' to get commands. Make sure to install on seperate computers and in this order.
FileServer: http://pastebin.com/pZkRjhGF
Bank Installer: http://pastebin.com/TQuqjQzq
Client Installer: http://pastebin.com/ymmhS9f3
Lyqyd #11
Posted 13 January 2015 - 10:21 PM
Why do you open the name file for writing, but never write anything to it?
If you look closely I do.

No. If you look closely, you might notice that you did not, and that it was, in fact, safetyscissors' code that fixed the problem in your code. You had used the "person" handle for both of the write operations, never writing anything to the "account" handle. If you actually read the code you posted, and the corrections he made, you will see that this was the case.