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

How to send a file over rednet

Started by turtledude01, 21 January 2013 - 10:56 AM
turtledude01 #1
Posted 21 January 2013 - 11:56 AM
I am trying to send files between my computers by simply haveing computer 1 run a program that sends a rednet broadcast that sais it needs the update file then it will run the update file that it grabs. That update file would then grab the rest of the files it needs from the server. I have tried many ways of doing this but i am not very good at programming (yet). Thanks to anyone that can help me!
lieudusty #2
Posted 21 January 2013 - 12:17 PM
First you open the file using the fs or io API. After reading the file send it over rednet and the receiving computer will save the file again using fs or io.
Luanub #3
Posted 21 January 2013 - 12:29 PM
If the file is a large read it into a table and use textutils.serialize() and textutils.unserialize() to convert it to a string and back to a table again after it is sent.
turtledude01 #4
Posted 21 January 2013 - 12:29 PM
Ok thanks. Ill see what i can do and if i cant get it to work correctly ill post what i come up with.
Luanub #5
Posted 21 January 2013 - 12:31 PM
if you want some examples just search this portion of the forums it is a very common question.
turtledude01 #6
Posted 21 January 2013 - 12:31 PM
If the file is a large read it into a table and use textutils.serialize() and textutils.unserialize() to convert it to a string and back to a table again after it is sent.
I dont know how to read it into a table :(/>
Edit: I also have searched the forum for it but i cant figure out other peoples programs very easily.
Luanub #7
Posted 21 January 2013 - 12:36 PM
Here is one way

local tContents = {} -- the contents table

local file = fs.open("FileNameHere", "r")
repeat
  line = file.readLine()
  table.insert(tContents,line)
until not line
file.close()
Eric #8
Posted 21 January 2013 - 12:38 PM
If the file is a large read it into a table and use textutils.serialize() and textutils.unserialize() to convert it to a string and back to a table again after it is sent.

Why on earth would you want to do that? You realize that the result of textutils.serialize() will be larger than the original file?
Luanub #9
Posted 21 January 2013 - 12:42 PM
If the file is a large read it into a table and use textutils.serialize() and textutils.unserialize() to convert it to a string and back to a table again after it is sent.

Why on earth would you want to do that? You realize that the result of textutils.serialize() will be larger than the original file?
Well can you send a table via rednet?
turtledude01 #10
Posted 21 January 2013 - 12:46 PM
If you could actually help me a bit more, I still am a massive noob at programming in LUA. I cant figure out how to send it whrough rednet and rebuild the file after it is sent. Then i want to run the file again whitch i know how to do, and it would then grab more files. And i dont know how to send the file after i use the example you gave me
Luanub #11
Posted 21 January 2013 - 12:59 PM
Try this out. It should work, but I haven't tested it.

SpoilerSend computer

local tContents = {}

write("Enter program to send: ")
local fileName = read()  -- example "startup" to send the startup file
write("Enter Computer ID to send to: ")
local toID = tonumber(read())

local file = fs.open(fileName, "r")  -- open file as read only
repeat  -- read the file line by line and insert into the table
  line = file.readLine()
  table.insert(tContents,line)
until not line
file.close()

local sContents = textutils.serialize(tContents) --change it to a string
rednet.send(toID, fileName..","..sContents)  --send it with the filename in front of it

Receive computer

local id,msg = rednet.receive()
local fileName,sContents = string.match(msg, "(%w+),(%w+)") -- split the file name from the contents
local tContents = textutils.unserialize(sContents) -- change to table
local file = fs.open(fileName,"w")
for x=1, #tContents do -- write the file line by line
  file.writeLine(tContents[x])
end
file.close()

This is very basic and will not handle files in directories without some modification. Just a simple example to get you going.
turtledude01 #12
Posted 21 January 2013 - 01:05 PM
Try this out. It should work, but I haven't tested it.

SpoilerSend computer

local tContents = {}

write("Enter program to send: ")
local fileName = read()  -- example "startup" to send the startup file
write("Enter Computer ID to send to: ")
local toID = tonumber(read())

local file = fs.open(fileName, "r")  -- open file as read only
repeat  -- read the file line by line and insert into the table
  line = file.readLine()
  table.insert(tContents,line)
until not line
file.close()

local sContents = textutils.serialize(tContents) --change it to a string
rednet.send(toID, fileName..","..sContents)  --send it with the filename in front of it

Receive computer

local id,msg = rednet.receive()
local fileName,sContents = string.match(msg, "(%w+),(%w+)") -- split the file name from the contents
local tContents = textutils.unserialize(sContents) -- change to table
local file = fs.open(fileName,"w")
for x=1, #tContents do -- write the file line by line
  file.writeLine(tContents[x])
end
file.close()

This is very basic and will not handle files in directories without some modification. Just a simple example to get you going.
Thanks, But i need to be able to have the sending computer triggered by a rednet message and send a full folder to the recieving computer
Luanub #13
Posted 21 January 2013 - 01:09 PM
Like I said a small example to get you going. No one here is going to write the entire thing for you. Will gladly help you as you run into issues. Read up on the FS, and rednet API's on the wiki page, you can read about the table and io api's here Lua 5.1 Reference Manual - contents

There are also some good tutorials here on the forums.
theoriginalbit #14
Posted 21 January 2013 - 01:10 PM
If the file is a large read it into a table and use textutils.serialize() and textutils.unserialize() to convert it to a string and back to a table again after it is sent.

Why on earth would you want to do that? You realize that the result of textutils.serialize() will be larger than the original file?
Well can you send a table via rednet?

local h = fs.open( path, "r" )
local contents = h.readAll()
h.close()
rednet.send( id, contents )
Why is a table needed? O.o
Luanub #15
Posted 21 January 2013 - 01:12 PM
If the file is a large read it into a table and use textutils.serialize() and textutils.unserialize() to convert it to a string and back to a table again after it is sent.

Why on earth would you want to do that? You realize that the result of textutils.serialize() will be larger than the original file?
Well can you send a table via rednet?

local h = fs.open( path, "r" )
local contents = h.readAll()
h.close()
rednet.send( id, contents )
Why is a table needed? O.o

Will that keep the formatting? I've never really used readAll(). Got in the habit of using tables with reading files when I started having files edit themselves to set persistent variables.
theoriginalbit #16
Posted 21 January 2013 - 01:14 PM
Thanks, But i need to be able to have the sending computer triggered by a rednet message and send a full folder to the recieving computer
Look into fs.list combined with fs.isDir, unless you want to create directories as well (then take a look at my file system Iterator in misc scripts in signature) and storing all the files in different table entries, then serialize the table and send. Receive, unserialize, loop through reading the table of files writing them to the computer.
turtledude01 #17
Posted 21 January 2013 - 01:17 PM
Ok Thanks anyways. Ill see if i can find some way of makeing this work. I just get really frustrated really fast when i cant figure stuff out
theoriginalbit #18
Posted 21 January 2013 - 01:18 PM
Will that keep the formatting? I've never really used readAll(). Got in the habit of using tables with reading files when I started having files edit themselves to set persistent variables.
Yes it preserves formatting. I always use read all, so that the handle is open for the shortest amount of time, then if I need a particular line I use my split string function in my Extended String Library to split it by \n to get a table of lines… Reason I do it this way is because if something happens and that file handle is still open, well it's annoying as hell!
ChunLing #19
Posted 21 January 2013 - 01:54 PM
I use:
function rply(mssgstr)
    print(mssgstr)
    if dt.rcID then rednet.send(dt.rcID,mssgstr) end
end
rcvfl = function(flnm) local cntnt flnm,cntnt = flnm:match("(%S+)%s*(.*)") local hndl = fs.open(flnm,"w") hndl.writeLine(cntnt) hndl.close()
return flnm.." updated" end
srvfl = function(flnm) flnm = flnm:match("%S+") local hndl = fs.open(flnm,"r") rply(hndl.readAll()) hndl.close()
return flnm.." served" end
Simple and reliable enough for me. srvfl() takes a file name (without spaces) and opens and sends the file using rply() (my rednet message thingy). rcvfl() takes a string that is headed by a file name separated from the rest of the file by spaces, and saves the remainder of the message under the filename.

They aren't really written to be used together, but there's no reason they couldn't be.
turtledude01 #20
Posted 21 January 2013 - 03:52 PM
I have 1 more question, Does anyone know a good computercraft ftp program? Ive looked but i cant find any that require no input on the server
ChunLing #21
Posted 21 January 2013 - 10:34 PM
You mean where you control all the file transfers remotely? I have one posted somewhere (it also does rednet relay and restricted access GPS hosting). There are others if you search around.