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

Reading text from file

Started by TheArchitect, 31 March 2013 - 07:29 PM
TheArchitect #1
Posted 31 March 2013 - 09:29 PM
Hello.

I'm trying to read text from a file line by line, but I can't quite figure out how. I've tried lots of things but none of them work.

What I've written from reading all over is:


file = fs.open("filetoread", "r");
line = file.readLine();
while not line==nil do
  if line == "this" then
    --do something or other
  elseif line == "that" then
    --do other stuff
  else
    write(line);
  end
  line = file.readLine();
end
file.close();

This however doesn't seem to work. The program doesn't enter the while loop, so I only get the very first line. I have looked all over but I haven't found references to reading all of a file line by line…

Thanks in advance for your attention and help :)/>
theoriginalbit #2
Posted 31 March 2013 - 09:39 PM
I'm not too sure what is going on there, unless I'm missing a small mistake being made.

given that your while condition says, while line is not nil…. is there anything in the file?

You could try using a different kind of loop, the repeat loop will always run once then evaluates its condition, see what happens with this one

local file = fs.open('filetoread', 'r')
local line
repeat
  line = file.readLine()
  -- do stuff with the line here
until not line
file.close()

alternatively you could try this, it is an iterator to loop through the lines in the file

local file = fs.open('filetoread', 'r')
for line in file:lines do
  -- do stuff with the line here
end

another option so that the file handle isn't open for a long time (since you're processing line by line) you could read all your lines into a table or read them all and split them into a table via new lines ( character: \n) and then read the tables.
remiX #3
Posted 31 March 2013 - 10:55 PM
while not line==nil do
can become
while line do

local file = fs.open('filetoread', 'r')
for line in file:lines do
  -- do stuff with the line here
end

Can you use a : with the fs api?
I think you meant this
for line in file.readLine do
theoriginalbit #4
Posted 31 March 2013 - 10:59 PM
Can you use a : with the fs api?
I think you meant this
for line in file.readLine do
whoops. yes. I combined the io and fs ways :P/>
the io way is

local h = io.open('someFile', 'r')
for line in h:lines do
  -- process line
end
TheArchitect #5
Posted 31 March 2013 - 11:05 PM
The file contains 15-20 lines of varying content. It is a template that is read then sent to a printer. Keyvalues are replaced within the loop.

Your first option almost works, but it chokes on the last iteration because it tries to concatenate the nil line.

I've tried your second option and I get "Function arguments expected" for the line that contains "for line in file:lines do".

remiX's "while line do" solution works (I actually expected a random string to be != true, so I hadn't tried that), thanks :D/>

I think the damned printer spit all the output in a single line, because the printout only shows the first line. I put debug prints in the loop and all the \n's are replaced with question marks. Is there a way to print a newline without resorting to setCursorPos()?
theoriginalbit #6
Posted 31 March 2013 - 11:43 PM
I've tried your second option and I get "Function arguments expected" for the line that contains "for line in file:lines do".
Yeh as remiX stated I made a syntactical error there…

Is there a way to print a newline without resorting to setCursorPos()?
I'm not 100% on this, but see if term.redirect works with a printer object. if it does then you can use

write('Some text')
and the words will be wrapped (then to print on the terminal again you will need to use term.restore)…. if the terminal can not be redirected to the printer then it will have to be done manual. take a look at bios.lua in the computercraft zip and take a look at the write function to see a goo way to word wrap… :)/>
TheArchitect #7
Posted 01 April 2013 - 12:12 AM
I guess I'll try that, or resort to setCursorPos(). Oh well.

Thanks! :D/>