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

[LUA][Files]Reading in paired values...

Started by Lost Ninja, 11 June 2013 - 02:13 AM
Lost Ninja #1
Posted 11 June 2013 - 04:13 AM
I have taken to generating an ini file for most of my more complex programs, this allows me to have one program that can do several different things without having to hard code it to do each one or use program arguments with every run. Currently I make a simple text file with a list of variables that the program needs and each program uses a different ini (though some values appear in all). How would I go about changing this so that the variable name and variable is stored in the file and then read so that I can have several (or all) programs running on that machine/turtle read the values in and only use the correct value?
	file = fs.open("ini","r")
		pName = tostring(file.readLine())
		prif = tostring(file.readLine())
		rOut = tostring(file.readLine())
		eType = tostring(file.readLine())
		cType = tostring(file.readLine())
		monitor = tonumber(file.readLine()) or tonumber(0)
		monSide = tostring(file.readLine()) or tostring("top")
		monName = tostring(file.readLine())
	file.close()

Is what I use to read values in (a battery monitor program in this instance).

Battery Monitor 2
bottom
right
te
mfr
0
left
monitor_1
The current ini for the above code.

pName  Battery Monitor 2
prif  bottom
rOut  right
eType  te
cType  mfr
monitor  0
monSide  left
monName  monitor_1
Example of same ini storing variable names.

I'm pretty confidant that I can generate the ini files, as above. But reading them back and splitting up the variable name/value, ignoring variable/value pairs for other programs and possibly stripping formatting has me stumped.

I'm guessing that I should read the whole file into a table then pulling out each pair and turning them back into a variable/value. Then just ignoring variables that the program doesn't use/need.
iniTable = {}
file = fs.open("ini","r")
	iniTable = file.readAll()
file.close()
iniPairs = #iniTable
for i = 1,iniPairs do
	<does something>
end
Again a guess, but I have no clue how to handle the actual <does something> section… HELP!!!

I know it is frowned upon to ask for example code, but if someone could provide me with some basic examples I'd be much obliged… :)/>
1lann #2
Posted 11 June 2013 - 04:18 AM
I would use textutils.serialize and textutils.unserialize. A handy dandy function to convert tables to a string, and back.

So I suppose in your example I would do something like this

local config = {}
config.pName = "Battery Monitor 2"
config.prif = "bottom"
config.everythingelse = "blah"

-- Saving
local f = io.open("/save", "w")
f:write(textutils.serialize(config))
f:close()

-- Loading
local f = io.open("/save", "r")
config = textutils.unserialize(f:read("*a"))
f:close()
And you would reference the variables like config.pName
Kingdaro #3
Posted 11 June 2013 - 04:38 AM
Serialization isn't very human-readable. I would prefer to use the type of format OP is already using, as it's easily understood and editable. A good way to load from and save to configuration files would be to use .readLine in a loop, and use string.match to match each of the lines' keys and values to a table.


local configPath = 'ini'
local config = {
	pName = 'Battery Monitor 2';
	prif = 'bottom';
	rOut = 'right';
	eType = 'te';
	cType = 'mfr';
	monitor = 0;
	monSide = 'left';
	monName = 'monitor_1';
}

function loadConfig()
	local loaded = {}
	if fs.exists(configPath) then
		local file = fs.open(configPath, 'r')
		for line in file.readLine do
			local key, value = line:match('([%w_]+)%s+(.*)')
			loaded[key] = value
		end
		return loaded, file.close()
	else
		return config
	end
end

function saveConfig()
	local content = ''
	for k,v in pairs(config) do
		content = content..k..' '..tostring(v)..'\n'
	end
	local file = fs.open(configPath, 'w')
	file.write(content)
	file.close()
end

config = loadConfig()
-- your script
saveConfig()

This line:

local key, value = line:match('([%w_]+)%s+(.*)')
It captures any sequence of one or more letters, digits or underscores, at least one space character, and whatever remains on the rest of the line. More on string matching: http://www.lua.org/manual/5.2/manual.html#6.4.1