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

Reading and writing files

Started by eastar, 29 June 2019 - 10:57 AM
eastar #1
Posted 29 June 2019 - 12:57 PM
Hello!

I don't know how to read from files effectively.
I have used the fh.readLine() function before, but since I didn't have much data to read from I used it a lame way:
Spoiler

--To use with Redpower Managers to prevent
--continuous item movement in tubesystem.
fn = "state"

--When no state file exists, info variable
--contains the first state of the tube
local info = {"closed",0}
local cycleCnt = 0
local step = 10 --resolution (in seconds)

--time while tube is closed = Step * maxClosed
local maxClosed = 11

--time while tube is open = Step * maxOpen
local maxOpen = 360

--redstone output for opener motor
tubeOpenerMotor = "left"

--redstone output for closer motor
tubeCloserMotor = "top"

function writeFile(table)
  fh = fs.open(fn,"w")
  for i=1, #table do
	fh.writeLine(tostring(table[i]))
  end
  fh.close()
end
function readFile()
  local table = {}
  local cnt = 1
  fh = fs.open(fn,"r")
  table[1] = fh.readLine()
  table[2] = tonumber(fh.readLine())
  fh.close()
  return table
end
function pushOut()
  rs.setOutput(tubeOpenerMotor,true)
  sleep(0.5)
  rs.setOutput(tubeOpenerMotor,false)
end
function pullIn()
  rs.setOutput(tubeCloserMotor,true)
  sleep(0.5)
  rs.setOutput(tubeCloserMotor,false)
end

if not fs.exists(fn) then
  writeFile(info)
else
  info = readFile()
end
term.clear()
term.setCursorPos(1,2)
print("Tube-mover is running!")
while true do
  if info[1] == "closed" then
	term.setCursorPos(2,3)
	term.clearLine()
	term.write("The tube is closed")
	pullIn()
	for cycleCnt = info[2], maxClosed do
	  term.setCursorPos(2,4)
	  term.clearLine()
	  term.write("Step: "..cycleCnt.."/"..maxClosed)
	  sleep(step)
	  info[2] = cycleCnt + 1
	  writeFile(info)  
	end
	pushOut()
	info[1] = "open"
	info[2] = 0
	writeFile(info)
  end

  if info[1] == "open" then
	term.setCursorPos(2,3)
	term.clearLine()
	term.write("The tube is open!")
	pushOut()
	for cycleCnt = info[2], maxOpen do
	  term.setCursorPos(2,4)
	  term.clearLine()
	  term.write("Step: "..cycleCnt.."/"..maxOpen)
	  sleep(step)
	  info[2] = cycleCnt + 1
	  writeFile(info)
	end
	pullIn()
	info[1] = "closed"
	info[2] = 0
	writeFile(info)
  end
end

As you can see in the readFile() function I use fh.readLine twice in a row. Now I would like to make a program, that reads in more data (probably 10 lines) from a file. I wouldn't like to use ten fh.readLine in a row.
I'm kinda sure that there is an easer, more elegant way of reading data, but how?

Thank you for the help!

eastar
Lupus590 #2
Posted 29 June 2019 - 02:10 PM
Have you read the wiki? Specifically the return value of fs.open
Edited on 29 June 2019 - 12:10 PM
eastar #3
Posted 29 June 2019 - 03:51 PM
Have you read the wiki? Specifically the return value of fs.open

Sorry, I probably don't understand you, but I have no idea how that could help me.
I do know how to open a file. I also know how to read or write a line to/from a file.

What I don't know is how to read multiple lines without much hassle.

But thanks for the help!
eastar #4
Posted 29 June 2019 - 05:47 PM
What I specifically would like is:
If I have a file containing data like this:

on
40
off
0
on
32
off
0
on
1

How would you read that into a table? especially if the you don't know how many lines the file contains.

Thanks again! :)/>
Edited on 29 June 2019 - 03:47 PM
Lupus590 #5
Posted 29 June 2019 - 08:08 PM
how does the data get into the file? If it's a program that you wrote then the easist way is to use texturils.serialise and unserialise
Dog #6
Posted 29 June 2019 - 09:38 PM
For the format you're using, I'd suggest using io.lines to read the file…

--# read the data
local myTable = { } --# declare and localize your table that will hold the data
for data in io.lines("/myFile") do --# start a loop that stops at the last data line in the file
  myTable[#myTable + 1] = data --# add the next line of data to the next table entry
end

--# print the data
for i = 1, #myTable do
  print(myTable[i])
end
eastar #7
Posted 30 June 2019 - 02:47 PM
For the format you're using, I'd suggest using io.lines to read the file…

--# read the data
local myTable = { } --# declare and localize your table that will hold the data
for data in io.lines("/myFile") do --# start a loop that stops at the last data line in the file
  myTable[#myTable + 1] = data --# add the next line of data to the next table entry
end

--# print the data
for i = 1, #myTable do
  print(myTable[i])
end

Thank you for the help! :)/>
Sadly in my version of CC io.lines() doesn't exist. (I'm using CC 1.5)
But thank you! I'l try something similar with h.readLine()!
Dog #8
Posted 30 June 2019 - 05:32 PM
Using h.readLine() you could do this…

local myTable = { }
local myFile = fs.open("/myFile", "r")
repeat --# start a loop that ends with a condition
  local line = myFile.readLine()
  if line then --# if the line read is not nil then add it to the table
    myTable[#myTable + 1] = line
  end
until line == nil --# end the loop if the line read is nil
myFile.close()
eastar #9
Posted 01 July 2019 - 08:31 PM
Using h.readLine() you could do this…

local myTable = { }
local myFile = fs.open("/myFile", "r")
repeat --# start a loop that ends with a condition
  local line = myFile.readLine()
  if line then --# if the line read is not nil then add it to the table
	myTable[#myTable + 1] = line
  end
until line == nil --# end the loop if the line read is nil
myFile.close()

OMG!!!
Thank you so much! :)/>

In the meantime I realised Lupus950 made a typo and meant textutils.serialize() and not textureils.serialize(). So I went with that one. But I'm glad you showed me this method. It makes sense now why there are loops that test the conditions at the end of the loop!

Big thanks to both of ya! :)/>
Edited on 01 July 2019 - 06:31 PM