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

Making an API

Started by Wing, 28 October 2012 - 10:14 PM
Wing #1
Posted 28 October 2012 - 11:14 PM
I just need a little help, i'm trying to get what is specifacally written on a single line in a file to return, but it isn't quite working. So I need help :D/>/>

function fileGetInfo(path,file,line)
fs.exists(path)
if (fs.exists(path) == true) then
    fs.exists(file)
    if (fs.exists("pos") == true) then
	    shell.setDir(path)
	    local files = fs.open(file, "r")
	    local fileData = {}
	    local lines = file.readLine()
	    repeat
	    table.insert(fileData,lines)
	    lines = files.readLine()
	    until lines == nil
	    file.close()
	    info = filedata[line]
	    return info
	    end
    end
end

THANKS!
snoble2022 #2
Posted 28 October 2012 - 11:19 PM
Hello, If you want to look at how to make a readLine function. Take a look at toxicwolf's WFCI api.
http://wolfos.co.uk
Wing #3
Posted 28 October 2012 - 11:25 PM
Tried searching for that API, didn't find anything. Problem is, I don't really know how "return" works. Thanks for trying though!
Lyqyd #4
Posted 28 October 2012 - 11:31 PM
Here is a slightly revised version of your function with comments added:


function fileGetInfo(path,file,lineNum)
	local path = fs.combine(path, file) --combine the path and file name.  You could even just use one argument, the full path.
	if fs.exists(path) then
		local fileHandle = io.open(file, "r") --open our file with the io library, because it is better.
		local fileData = {}
		if fileHandle then --check the file handle anyway, just to make sure.
			for line in fileHandle:lines() do --for every line in the file,
				table.insert(fileData, line) --add the line to the table.
			end
			file:close()
			if fileData[lineNum] then --if our line number refers to an actual line of the file.
				return fileData[lineNum]
			else
				return nil, "Line number out of range!"
			end
		else
			return nil, "Error opening file!"
		end
	else
		return nil, "File not found!"
	end
end

Edit: Saw your second post. Return passes values back, so you'd use this function like this:

lineContents = fileGetInfo("/path/to", "file", 4)

It would then open the file at /path/to/file, read the file into the table and return the contents of the fourth entry in the table, which would be line four.
ChunLing #5
Posted 28 October 2012 - 11:34 PM
return terminates a function and provides a value (or multiple values) so that if you say something like
"variablename = fileGetInfo(path,file,line)" then variablename will have the value returned from fileGetInfo().

In the case above, the error returns are nil,"an error message". This allows the function to be used in a conditional, and return false for the conditional, but also allows the errors to be captured and output if this is desired.
Wing #6
Posted 28 October 2012 - 11:35 PM
Thanks! I like really quick responses :D/>/>
I'll post in the same thread if I have any more trouble.
Edit:
If the file is saved in the API's folder (inside mod folder) do I need to load the API?
Secondly, if I save the file as "wf" do I use it as "wf.fileGetInfo(path,file,lineNum)"?
Wing #7
Posted 29 October 2012 - 12:05 AM
Lyqyd I can't get the function to print the information on the line, it just prints blank!

lineContents = wf.fileGetInfo("/.main/users,"lyqyd",2)
print(lineContents)
Lyqyd #8
Posted 29 October 2012 - 12:35 AM
Corrected code:


function fileGetInfo(path,file,lineNum)
    local path = fs.combine(path, file) --combine the path and file name.  You could even just use one argument, the full path.
    if fs.exists(path) then
        local fileHandle = io.open(path, "r") --open our file with the io library, because it is better.
        local fileData = {}
        if fileHandle then --check the file handle anyway, just to make sure.
            for line in fileHandle:lines() do --for every line in the file,
                table.insert(fileData, line) --add the line to the table.
            end
            fileHandle:close()
            if fileData[lineNum] then --if our line number refers to an actual line of the file.
                return fileData[lineNum]
            else
                return nil, "Line number out of range!"
            end
        else
            return nil, "Error opening file!"
        end
    else
        return nil, "File not found!"
    end
end
Wing #9
Posted 29 October 2012 - 12:45 AM
umm, :1: ')' expected, when trying to run,
lineContents = wf.fileGetInfo("/.main/users,"lyqyd",2)
print(lineContents)
Lyqyd #10
Posted 29 October 2012 - 12:46 AM
You're missing a quote:

lineContents = wf.fileGetInfo("/.main/users","lyqyd",2)
Wing #11
Posted 29 October 2012 - 12:48 AM
omg, this is complicated, now getting attempt to index ? (a nil value)
edit: ill check back tomorrow
remiX #12
Posted 29 October 2012 - 06:39 PM
omg, this is complicated, now getting attempt to index ? (a nil value)
edit: ill check back tomorrow

Whats the number that was with the line?

Edit: I tested it and it works perfectly .. I removed the 'nil's where it returns because it then doesn't print the error, no clue why.


function fileGetInfo(path,file,lineNum)
    local path = fs.combine(path, file) --combine the path and file name.  You could even just use one argument, the full path.
    if fs.exists(path) then
	    local fileHandle = io.open(path, "r") --open our file with the io library, because it is better.
	    local fileData = {}
	    if fileHandle then --check the file handle anyway, just to make sure.
		    for line in fileHandle:lines() do --for every line in the file,
			    table.insert(fileData, line) --add the line to the table.
		    end
		    fileHandle:close()
		    if fileData[lineNum] then --if our line number refers to an actual line of the file.
			    return fileData[lineNum]
		    else
			    return "Line number out of range!"
		    end
	    else
		    return "Error opening file!"
	    end
    else
	    return "File not found!"
    end
end

i = tonumber(read())
print(fileGetInfo("","lol",i))

This wasn't tested in an API though.
Lyqyd #13
Posted 29 October 2012 - 06:53 PM
omg, this is complicated, now getting attempt to index ? (a nil value)
edit: ill check back tomorrow

Whats the number that was with the line?

Edit: I tested it and it works perfectly .. I removed the 'nil's where it returns because it then doesn't print the error, no clue why.


function fileGetInfo(path,file,lineNum)
    local path = fs.combine(path, file) --combine the path and file name.  You could even just use one argument, the full path.
    if fs.exists(path) then
	    local fileHandle = io.open(path, "r") --open our file with the io library, because it is better.
	    local fileData = {}
	    if fileHandle then --check the file handle anyway, just to make sure.
		    for line in fileHandle:lines() do --for every line in the file,
			    table.insert(fileData, line) --add the line to the table.
		    end
		    fileHandle:close()
		    if fileData[lineNum] then --if our line number refers to an actual line of the file.
			    return fileData[lineNum]
		    else
			    return "Line number out of range!"
		    end
	    else
		    return "Error opening file!"
	    end
    else
	    return "File not found!"
    end
end

i = tonumber(read())
print(fileGetInfo("","lol",i))

This wasn't tested in an API though.

The nil return followed by an error string is a lua convention. How do you now tell the difference between an error and a line in a file that is identical to the error strings? The nils were there for a reason and should not be removed.
remiX #14
Posted 29 October 2012 - 07:22 PM
— snip

The nil return followed by an error string is a lua convention. How do you now tell the difference between an error and a line in a file that is identical to the error strings? The nils were there for a reason and should not be removed.

Make sense. I don't know much about return just yet :P/>/>

Tested it using it as an API and it works fine. The error you're getting might be because of this line:

for line in fileHandle:lines() do --for every line in the file,
I got the same error, so I changed it into a repeat:
Spoiler
function fileGetInfo(path,file,lineNum)
	local path = fs.combine(path, file) --combine the path and file name.  You could even just use one argument, the full path.
	if fs.exists(path) then
		local fileHandle = fs.open(path, "r") --open our file with the io library, because it is better.
		local fileData = {}
		if fileHandle then --check the file handle anyway, just to make sure.
			repeat
				line = fileHandle.readLine()--for every line in the file,
				table.insert(fileData, line) --add the line to the table.
			until line == nil
			fileHandle.close()
			if fileData[lineNum] then --if our line number refers to an actual line of the file.
				return fileData[lineNum]
			else
				return nil, "Line number out of range!"
			end
		else
			return nil, "Error opening file!"
		end
	else
		return nil, "File not found!"
	end
end

And to test I used this:

Spoiler
term.clear() term.setCursorPos(1,1)
filePath = read()
fileName = read()
fullPath = fs.combine(filePath, fileName) -- was just to check
lineNumber = tonumber(read())
os.loadAPI("gi")
print("File Path: "..filePath.."nFile Name: "..fileName.."nFull Path: "..fullPath.."nLine Number: "..lineNumber.."n")
print(gi.fileGetInfo(filePath,fileName,lineNumber))

This works great, I'm actually going to start using it :P/>/>
Wing #15
Posted 29 October 2012 - 07:27 PM
Ok ill need to check this out thanks for all the input, I feel like total retard now…
ChunLing #16
Posted 29 October 2012 - 08:38 PM
If you want to get the error, then do a multiple assignment (or a table assignment). "info,errormessage = fileGetInfo("","lol",i)"

Then you have the info if there was any, and the errormessage if there was no info. And your program can instantly tell the difference, so you can say something like:
if info then print(info) else print(errormessage) end
Lyqyd #17
Posted 29 October 2012 - 09:07 PM
Tested it using it as an API and it works fine. The error you're getting might be because of this line:

for line in fileHandle:lines() do --for every line in the file,

If you were getting errors on that line using my corrected code, you probably broke your io.open. It worked perfectly well for me.
Wing #18
Posted 30 October 2012 - 12:26 AM
Back! This code isn't writing in the second file… Have fun, I should start a daily code fix challenge!


function fileExec(path,file,path2,file2)
local path = fs.combine(path, file)
local path2 = fs.combine(path2,file2)
if fs.exists(path) then
local fileHandle = fs.open(path, "r")
local fileData = {}
	 if fileHandle then
	 repeat
		  line = fileHandle.readLine()
			table.insert(fileData, line)
		until line == nil
		 fileHandle.close()
		 local fileHandle2 = fs.open(path2,"w")
		 if filehandle2 then
		 data = 1
			 repeat
			 fileHandle2.writeLine(fileData[data])
				 data = data +1
			 until (fileData[data] == nil)
			 fileHandle2.close()
		 else
		 return nil, "Error opening file!"
			 end
else
		 return nil, "Error opening file!"
		 end
else
		return nil, "File not found!"
		end
end
EDIT:
FIXED CODE:

function fileExtract(path,file,path2,file2)
local path3 = path2
local file3 = file2
local path = fs.combine(path, file)
local path2 = fs.combine(path2,file2)
if fs.exists(path) then
  local fileHandle = fs.open(path, "r")
  local fileData = {}
	 if fileHandle then
	  repeat
		   line = fileHandle.readLine()
		    table.insert(fileData, line)
		 until line == nil
		 fileHandle.close()
		 local fileHandle2 = fs.open(path2,"w")
		 if fileHandle2 then
		  data = 1
			 repeat
			   fileHandle2.writeLine(fileData[data])
				  data = data +1
			 until (fileData[data] == nil)
			 fileHandle2.close()
		 else
		  return nil, "Error opening file!"
			 end
  else
		 return nil, "Error opening file!"
		 end
else
	    return nil, "File not found!"
	    end
end