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

saving files/tables

Started by nirokid, 17 September 2012 - 03:16 PM
nirokid #1
Posted 17 September 2012 - 05:16 PM
Is there any way to save tables or a string? I want to create a mail system and I want to save the messages.

thank you
Cranium #2
Posted 17 September 2012 - 05:21 PM
There are many ways to save tables and strings. What are you trying to do? Are you wanting to write to a file?
nirokid #3
Posted 17 September 2012 - 05:24 PM
first of all thank you for helping me :)/>/>,

I want to to save a message that a computer get from another computer. then I just want to read it so lets say computer 1 sends computer 2 a message called a then I wand to save this message a in a file so that I can read it later.
Rsstn #4
Posted 17 September 2012 - 05:24 PM
Use this to help you learn how to create/open/read/write/close files:
http://computercraft...?title=Fs_(API)

You can't save tables in this way. To save tables, you must first convert them into a string using:

textutils.serialize(TABLE_NAME)

To turn a string back into a table, use:

textutils.unserialize(STRING_NAME)
Kolpa #5
Posted 17 September 2012 - 05:26 PM
if you want to write a table to a file do this:

function save(table,name)
local file = fs.open(name,"w")
file.write(textutils.serialize(table))
file.close()
end
to load do this:


function load(name)
local file = fs.open(name,"r")
local data = file.readAll()
file.close()
return textutils.unserialize(data)
end

——————————————————————————————————-

if you want to write text to a file do this:

function save(text,name)
local file = fs.open(name,"w")
file.write(text)
file.close()
end
to load do this:


function load(name)
local file = fs.open(name,"r")
local data = file.readAll()
file.close()
return data
end
Rsstn #6
Posted 17 September 2012 - 05:28 PM
first of all thank you for helping me :)/>/>,

I want to to save a message that a computer get from another computer. then I just want to read it so lets say computer 1 sends computer 2 a message called a then I wand to save this message a in a file so that I can read it later.

For this, you probably won't need tables.
You can just use the FS API to save the string to a file on the PC. When you want to show the message again, you can just use the FS API to open the file as a string, and print the string to the screen.
GopherAtl #7
Posted 17 September 2012 - 05:34 PM

  --strings are easy
  local myString="This is my string. There are many like it but this one is mine."
  --just open a file for writing (first param is filename, 2nd tells it to open for writing)
  local file=fs.open("saved_string","w")
  --and write the string
  file.write(myString)
  --always remember to close the file when you're done, or it won't actually save!
  file.close()

  --tables are almost as easy.
  local myTable={name="bob", age=16, projects={"locked door", "menus" }}
  --just make it into a string first with textutils.serialize
  local tableString=textutils.serialize(myTable)
  --and write as before
  file=fs.open("saved_table","w")
  file.write(tableString)
  file.close()

  --loading back is very similar.
  local myString
  --first open the file. 2nd parameter is "r" for "read" this time!
  local file=fs.open("saved_string","r")
  --and read it!
  myString=file.readAll()
  --still close file when done
  file.close()

  --and the table, same but unserialize
  local file=fs.open("saved_table","r")
  local tableString=file.readAll()
  file.close() --already done reading, so close now
  --unserialize the string back to a table!
  local myTable=textutils.unserialize(tableString)

  --if you wanna save multiple variables at once, just put them all in a table first, ex:
  local myVariables={}
  myVariables.myString=myString
  myVariables.myTable=myTable
  --then serialize and write myVariables exactly as we did myTable in the example above

  --load back same as load table example above, and after deserializing, you can separate the vars again
  local myTable=myVariables.myTable
  local myString=myVariables.myString

:edit: wow, 5 posts while I was typing this. The mythical pentuple ninja - he exists!
Kolpa #8
Posted 17 September 2012 - 05:37 PM

  --strings are easy
  local myString="This is my string. There are many like it but this one is mine."
  --just open a file for writing (first param is filename, 2nd tells it to open for writing)
  local file=fs.open("saved_string","w")
  --and write the string
  file.write(myString)
  --always remember to close the file when you're done, or it won't actually save!
  file.close()

  --tables are almost as easy.
  local myTable={name="bob", age=16, projects={"locked door", "menus" }}
  --just make it into a string first with textutils.serialize
  local tableString=textutils.serialize(myTable)
  --and write as before
  file=fs.open("saved_table","w")
  file.write(tableString)
  file.close()

  --loading back is very similar.
  local myString
  --first open the file. 2nd parameter is "r" for "read" this time!
  local file=fs.open("saved_string","r")
  --and read it!
  myString=file.readAll()
  --still close file when done
  file.close()

  --and the table, same but unserialize
  local file=fs.open("saved_table","r")
  local tableString=file.readAll()
  file.close() --already done reading, so close now
  --unserialize the string back to a table!
  local myTable=textutils.unserialize(tableString)

  --if you wanna save multiple variables at once, just put them all in a table first, ex:
  local myVariables={}
  myVariables.myString=myString
  myVariables.myTable=myTable
  --then serialize and write myVariables exactly as we did myTable in the example above

  --load back same as load table example above, and after deserializing, you can separate the vars again
  local myTable=myVariables.myTable
  local myString=myVariables.myString

:edit: wow, 5 posts while I was typing this. The mythical pentuple ninja - he exists!

try using functions next time and separate the code tags that's a monster to read
GopherAtl #9
Posted 17 September 2012 - 05:39 PM
You think so? it's 50% comments and whitespace. I find explanations in the form of code help people learn to read and understand code better. ymmv. Since I'm replying anyway, did you reallyneed to quote the whole block of text in the previous post you were commenting on?
Cranium #10
Posted 17 September 2012 - 05:44 PM
If it's messages, then yes, you do want to save as strings. You can use commas to differentiate from the sender, time, and message.

local function saveMsg(saveTable)
    local file = fs.open("status", "w")
    if file then
	    for eNum, eInfo in ipairs(saveTable) do
		    file.writeLine(eInfo.time..","..eInfo.user..","..eInfo.message)
	    end
	    file.close()
    end
end
local function loadMsg()
    local loadTable = {}
    local file = fs.open("status", "r")
    if file then
	    readLine = file.readLine()
	    while readLine do
		    local lineTable = {}
		    lineTable.time, lineTable.user, lineTable.message = string.match(readLine, "(%w+),(%w+),(%w+)")
		    if lineTable.type then
			    table.insert(loadTable, lineTable)
		    end
		    readLine = file.readLine()
	    end
	    file.close()
    end
    return loadTable
end
I have used this before with my messaging, and it seems to work ok.
Kolpa #11
Posted 17 September 2012 - 05:46 PM
You think so? it's 50% comments and whitespace. I find explanations in the form of code help people learn to read and understand code better. ymmv. Since I'm replying anyway, did you reallyneed to quote the whole block of text in the previous post you were commenting on?
:)/>/> now you are talking about an block of text as well the point is that it looks kind of scary to just look at this wall of text instead of giving them something like this:

to save a table:

function save(table,name)
local file = fs.open(name,"w")
file.write(textutils.serialize(table))
file.close()
end



its just something that i found out helps with the understanding more than just putting a wall of text in front of them
Dimmick #12
Posted 06 July 2013 - 04:18 PM
How's about nested tables?

do I just:


for i,v in ipairs(table) do
file.print(textutils.serialize(v))
end

or?

And how's about reading,


file = fs.open("myfile". "r")
tab = {}
for i = 1, #file do
table.insert(tab, textutils.unserialize(file.readLine()))
end

Or am I completely off?
albrat #13
Posted 07 July 2013 - 10:58 AM

-- Varible - our table...
local usrbase = {}
--nested table write
function newUser(user, pass) -- insert data
  local u = {}
  u[1] = user
  u[2] = pass
  return u
end
-- Save DataBase
function saveDB(filename, theTable)  -- call with saveDB (file, tablename)
  theTable = textutils.serialize(theTable)
  local file = fs.open(filename, "w")
  file.write(textutils.serialize(theTable))
  file.close()
end
-- append DataBase
function appDB(filename, theTable)  -- call with saveDB (file, tablename)
  theTable = textutils.serialize(theTable)
  local file = fs.open(filename, "a")
  file.write(textutils.serialize(theTable))
  file.close()
end
-- Load DataBase
function loadDB(filename)  --  Call with  tablename = loadDB(filename)
  file = fs.open(filename, "r")
  local content = file.readAll()
  file.close()
  return textutils.unserialize(content)
end

-- Call our table save by the way this is a example insert into table
--[[ insert to tables. This is a one time run to insert my passwords
-- comented code currently inactive due to already having created the file
table.insert(usrbase, newUser("admin","pass3"))
table.insert(usrbase, newUser("guest","pass1"))
table.insert(usrbase, newUser("user","pass2"))
saveDB("userbase", usrbase)
sleep(2)
--]]
---[[ LoadDB  This loads the database into our system
usrbase = textutils.unserialize(loadDB("userbase"))
--]]

I had troubles with some conversions just giving me a set of tables that i could not recall after the reload.
This system returned a table I could still recall.

to recall data from the table I used this bit of code.


  for i= 1, #usrbase do
   if pas == usrbase[i][2] then  -- If the message matches a user password set our response to true
    valid = true 
    password = usrbase[i][2]
    break
   else
    valid = false  -- if no password matches...
   end
  end

Please note that the above code is checking our Passwords (usrbase[2]) against a message received from another computer.

The script is checking a index of 1,2,3,4,5,6…. which contains 2 varibles in the table. Username , password. With a few tweaks this could be changed to simply print the table then clear it after.

fx ..

  for i= 1, #usrbase do
    print(usrbase[i][1], .." > "..usrbase[i][2])
  end

This would output every entry in the table.
albrat #14
Posted 07 July 2013 - 11:16 AM
this code is not tested, but it is made from bits of my servers code…

messagelist = {}
function newUser(user, pass) -- insert data
  local u = {}
  u[1] = user
  u[2] = pass
  return u
end
-- Outputter
function outputter(list)
if #list =< 0 then return false end
  for i = 1, #list do
   print(list[i][1], .." > "..list[i][2])
  end
end
-- Split script
function string:split( inSplitPattern, outResults )
   if not outResults then
	  outResults = { }
   end
   local theStart = 1
   local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
   while theSplitStart do
	  table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) )
	  theStart = theSplitEnd + 1
	  theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart )
   end
   table.insert( outResults, string.sub( self, theStart ) )
   return outResults
end
while true do
term.setCursorPos(1,1)
print("press [1] to read messages")

local osevent, input, m, d = os.pullEvent()  -- osevent = event, input = id or input, m = message,  d = distance
s = input  -- s = senderID

if input == 2 and osevent == "char" then
   outputter(tablemes)
elseif s == nil then break
-- when you send from the source computer use a * to seperate the username and message


else
  tablemes = string.split(m, "*")  --  This is the string splitter function
  user = tablemes[1]
  message = tablemes[2]

  table.insert(messagelist, newUser(user, message))

end
end