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

storing tables to file and reading them back to a table

Started by andyoc, 30 January 2014 - 12:47 PM
andyoc #1
Posted 30 January 2014 - 01:47 PM
so i am in the process of building a programme that checks blocks in game this is only for learning purposes but after i read a block and store it to a variable how do i save it and then read from it this is what i have so far


function write()
file = fs.open("Blocks","w")
blocks = {}
blocks[1] = {id = 00,name = "air"}
blocks[2] = {id = 01,name = "stone"}
blocks[3] = {id = 02,name = "grass block"}
blocks[4] = {id = 03,name = "dirt"}
blocks[5] = {id = 08,name = "water"}
blocks[6] = {id = 10,name = "lava"}
blocks[7] = {id = 12,name = "sand"}
blocks[8] = {id = 13,name = "gravel"}
blocks[9] = {id = 14,name = "gold ore"}
blocks[10] = {id = 15,name = "iron ore"}
blocks[11] = {id = 16,name = "coal ore"}
blocks[12] = {id = 21,name = "lapis lazuli ore"}
blocks[13] = {id = 24,name = "sandstone"}
blocks[14] = {id = 56,name = "diamond ore"}
blocks[15] = {id = 73,name = "redstone ore"}
blocks[16] = {id = 78,name = "snow"}
blocks[17] = {id = 79,name = "ice"}
blocks[18] = {id = 80,name = "snow block"}
blocks[19] = {id = 82,name = "clay block"}
blocks[20] = {id = 11,name = "mycelium"}
blocks[21] = {id = 120,name = "end portal block"}
blocks[22] = {id = 129,name = "emerald ore"}
blocks[23] = {id = 174,name = "packed ice"}
for i = 1,#blocks do
  file.writeLine(blocks[i])
end
file.close()
end
function read()
file = fs.open("Blocks","r")
Blocks = {}

Blocks[1] = file.readLine()
print(Blocks[1])


end

write()
read()

can anyone help help me

the problem i have is not reading it reads fine but it reads the {} in the block i just want it to store into a nested table of id example
Block[1]
id,1
name,Stone
Block[2]
id,2
name,Grass Block
Edited on 30 January 2014 - 12:56 PM
surferpup #2
Posted 30 January 2014 - 02:08 PM
Try the textutils.serialize() function. It will serialize your blocks {} table for you into a string. textutils.unserialize() will take a string and turn it into a table for you. See the wiki entry on textutils.

You will end up writing the serialized version of your table to a file for storage. When you read it in, you are reading a single string with which you will then unserialize back into your blocks{} table.
Edited on 30 January 2014 - 01:08 PM
andyoc #3
Posted 30 January 2014 - 02:50 PM
and what about reading back basically what i want to do is compare a block to the data
i have tried this before but unsure how to call a nested table when i print this now using

for k,v in pairs(Blocks[1]) do
print(k.." "..v)
end
i get an output of
id0
nameair

this is all new to me so i dont know how to seperate it so i can compare it
what i want to accomplish is for example
if turtle.detect() == Blocks[1{id}] then
print(Blocks[1{name}]
end
CometWolf #4
Posted 30 January 2014 - 03:40 PM
Turtle.detect dosen't return ids… It returns true if there is a block in the given direction, and false otherwise. As for your loop, k is the table key, and v is the value held by the key. What you want is just a regular for loop

for i = 1,#blocks do
  if blockId = blocks[i].id then
    print blocks[i].name
    break
  end
end
Edited on 30 January 2014 - 02:43 PM
andyoc #5
Posted 30 January 2014 - 03:50 PM
i just used that as an example mate but thanks that makes sence :)/>


well it did until testing so i dont think i have nested the table correctly im such a noob

is this correct?


Blocks = {}
Blocks[1] = {[ID] = 1,[Name] = "Stone"}
Edited on 30 January 2014 - 03:10 PM
Bomb Bloke #6
Posted 30 January 2014 - 05:01 PM
That's a valid way of defining the table, yes.

Comet's example assumes you've got a "blockId" variable defined somewhere. In searches your table for a match, and prints the block's name if it finds one. If "blockId" isn't set to anything it'll find no such match and won't do anything visible at all. Bear in mind there is no command in vanilla ComputerCraft that can be used to get block IDs from the world.

Also note that "Blocks[1]" is not the same as "blocks[1]". Capitalisation matters.
CometWolf #7
Posted 30 January 2014 - 05:13 PM
is this correct?

Blocks = {}
Blocks[1] = {[ID] = 1,[Name] = "Stone"}
This is invalid syntax. Lua assumes you're using a variable, unless you use quotation marks. So unless you define the variables name and ID beforehand, it won't work.
The indentation and multi lines in the following example are not nessacary, but it makes it a lot easier to read.

tBlocks = { --the "t" at the start of a table name is just a personal preference
  [1] = {
    ["ID"] = 1,
    ["name"] = "Stone"
  }
}
Bomb Bloke #8
Posted 30 January 2014 - 05:29 PM
Ah. The quotes. I'm always forgetting the quotes.
surferpup #9
Posted 30 January 2014 - 08:37 PM
Both of these are valid, although the second one is easier to do as well as read:

myTable = {
  ["ID"] = 1;
  ["name"] = "Stone";
}

myTable = {
  ID = 1;
  name = "Stone";
}
andyoc #10
Posted 31 January 2014 - 12:41 PM
Both of these are valid, although the second one is easier to do as well as read:

myTable = {
  ["ID"] = 1;
  ["name"] = "Stone";
}

myTable = {
  ID = 1;
  name = "Stone";
}

But this would involve multiple first point variables example

myTable = {
    ["ID"] = 1;
    ["Name] = "Stone";
}
myTable2 = {
    ["ID"] = 2;
    ["Name"] = "Grass Block";
}
--where I want
myTable = {
    [1] = {
             ["ID"] = 1
             ["Name"] = "Stone"
             }
    [2] = {
             ["ID"] = 2
             ["Name"] = "Stone"
             }
}

anyway I think I have a good grasp now thank you everyone

p.s I know Vanilla CC does not have any methods to get block id but I am working with immibus peripherals which does ;)/>
surferpup #11
Posted 31 January 2014 - 12:53 PM
And you missed the point of my response. So, using your example:


myTable = {
	[1] = {
			 ["ID"] = 1,
			 ["Name"] = "Stone"
			 },
	[2] = {
			 ["ID"] = 2,
			 ["Name"] = "Stone"
			 }
}

-- is equivalent to


myTable = {
	[1] = {
			 ID = 1,
			 Name = "Stone"
			 },
	[2] = {
			 ID = 2,
			 Name = "Stone",
			 }
}

Which one do you think is easier to code? BTW – notice the commas in my examples. They are missing in yours. That will cause you problems.
Edited on 31 January 2014 - 11:56 AM
Kingdaro #12
Posted 31 January 2014 - 01:50 PM
I feel like this doesn't need much expansion, but I would probably just do away with the [1], [2] junk too. Smaller tables like that also don't really need to be expanded, since they're easy enough to read. I also prefer to use semicolons when putting them on new lines.


tab = {
  {id = 1, name = 'stone'};
  {id = 2, name = 'grass'};
}

But yeah, there are a lot of different ways to do it.
surferpup #13
Posted 31 January 2014 - 02:04 PM
I agree with getting rid of the [1] and [2], but I was copying style. I like the semi-colon concept as well, just didn't want to confuse the issue. In addition (just to add more confusion) semi-colons fail as separators when it is a table of functions.
Edited on 31 January 2014 - 01:05 PM
andyoc #14
Posted 31 January 2014 - 03:30 PM
@Kingdaro

but that would just replace id and name every time you add the table I need it to store all the values throughout the file without calling 2 many variables
Edited on 31 January 2014 - 02:31 PM
andyoc #15
Posted 31 January 2014 - 04:26 PM
sooo just tried this


Blocks = {
			   [1] = {
					    ["ID"] = 1,
					    ["Name"] = "Stone"
					    }
			   
 
			   [2] = {
					    ["ID"] = 2,
					    ["Name"] = "Grass"
					    }
			    }
 

and it just errors saying close the { at line 3 can someone just give me a way of doing this I'm past the point of breaking point
CometWolf #16
Posted 31 January 2014 - 05:12 PM
Note what Surf said earlier.
BTW – notice the commas in my examples. They are missing in yours. That will cause you problems.

Blocks = {
						   [1] = {
											["ID"] = 1,
											["Name"] = "Stone"
											}, -- comma here, to seperate Blocks entries
						  

						   [2] = {
											["ID"] = 2,
											["Name"] = "Grass"
											}
							}

Also sorry for any confusion, what they are saying is these are the same, and will both work the same way

["ID"] = 1
ID = 1

This however, is not, and won't work unless you define the variable ID previously.

[ID] = 1
Edited on 31 January 2014 - 04:15 PM
andyoc #17
Posted 31 January 2014 - 05:30 PM
are you kidding me hahaha im more frustrated I didn't think of that then missing it out I think ive tried everything under the sun to get this to work "Except That" hahaha cheers Comet you he man

one more question on reading back from a file is there anyway to check how many lines are in the file and put it into a for loop because I keep getting error message concatenate string and nil



function read()
file = fs.open("Blocks","r")
Blocks = {}
readFile = file.readLine()
Blocks[1] = textutils.unserialize(readFile)
print(Blocks[1].id)
end

ive tried


while file.readLine() ~= nil do

but it reads the Line and moves onto the next????
Edited on 31 January 2014 - 04:52 PM
Kingdaro #18
Posted 31 January 2014 - 07:01 PM
@Kingdaro

but that would just replace id and name every time you add the table I need it to store all the values throughout the file without calling 2 many variables
No, this:

tab = {
  {id = 1, name = 'stone'};
  {id = 2, name = 'grass'};
}

Is equivalent to this:

tab = {
  [1] = {id = 1, name = 'stone'};
  [2] = {id = 2, name = 'grass'};
}
Edited on 31 January 2014 - 06:02 PM
CometWolf #19
Posted 31 January 2014 - 07:07 PM
one more question on reading back from a file is there anyway to check how many lines are in the file and put it into a for loop because I keep getting error message concatenate string and nil
function read()
file = fs.open("Blocks","r")
Blocks = {}
readFile = file.readLine()
Blocks[1] = textutils.unserialize(readFile)
print(Blocks[1].id)
end

ive tried

while file.readLine() ~= nil do

but it reads the Line and moves onto the next????
the serialized table will be written to just one line anyways, so all you really need is to call file.readLine(). But what you generally do when you want the whole file, is use file.readAll(), which returns all lines. To get each line seperately, you could do some gmatch tricker, or the way i usually do it

tLines = {}
local line = file.readLine()
while line do -- this is the same as "while line ~= nil do"
  tLines[#tLines+1] = line
  line = file.readLine()
end
Edited on 31 January 2014 - 06:08 PM
andyoc #20
Posted 01 February 2014 - 11:57 AM
Comet Wolf you are the man thanks alot for all your help i now have a better understanding of Variables thanks to you