Reading and Writing Tables to Files

User avatar
octacian
Member
 
Posts: 408
Joined: Mon Dec 21, 2015 22:18
GitHub: octacian
IRC: octacian
In-game: octacian

Reading and Writing Tables to Files

by octacian » Mon Jun 20, 2016 19:20

What is the easiest way to write, read, and edit tables stored within files? I need to store in a database-like file records of players that are warned or kicked for using inappropriate words in the chat so that the "punishment" is taken to a new level after a certain number of attempts.

I'd also like to use a table/database to store the words that trigger the warning or kick, and to improve the default ban function to work something like xban2.

Speaking of xban2, I tried looking at the code as well as the lua-users wiki but couldn't make sense of anything. If someone can provide me with a detailed explanation of how to read tables from files, as well as write and edit content, I would really appreciate it.
God isn't dead!

My Coolest Mods:
MicroExpansion, Working Computers, Interchangeable Hands

Check out my YouTube channel! (octacian)
 

User avatar
rubenwardy
Member
 
Posts: 4500
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: Reading and Writing Tables to Files

by rubenwardy » Mon Jun 20, 2016 19:25

Note that the data you save, in this case awards.players, must not contain any functions or user data (such as player/entity objects or itemstacks)

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
function awards.save()
   local file = io.open(minetest.get_worldpath().."/awards.txt", "w")
   if file then
      file:write(minetest.serialize(awards.players))
      file:close()
   end
end

function awards.load()
   local file = io.open(minetest.get_worldpath().."/awards.txt", "r")
   if file then
      local table = minetest.deserialize(file:read("*all"))
      if type(table) == "table" then
         return table
      end
   end
   return {}
end
 

User avatar
octacian
Member
 
Posts: 408
Joined: Mon Dec 21, 2015 22:18
GitHub: octacian
IRC: octacian
In-game: octacian

Re: Reading and Writing Tables to Files

by octacian » Mon Jun 20, 2016 20:09

Thanks!

If I want to remove an entry, I assume I just set it to nil?

Any good resources on tables? I have basic understanding, and I'm sure I'll find something, however, if you know a worthwhile resource that would be great.
God isn't dead!

My Coolest Mods:
MicroExpansion, Working Computers, Interchangeable Hands

Check out my YouTube channel! (octacian)
 

User avatar
rubenwardy
Member
 
Posts: 4500
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: Reading and Writing Tables to Files

by rubenwardy » Tue Jun 21, 2016 01:06

Yes, setting to nil will delete it.

Read this: https://www.lua.org/pil/2.5.html
 

User avatar
octacian
Member
 
Posts: 408
Joined: Mon Dec 21, 2015 22:18
GitHub: octacian
IRC: octacian
In-game: octacian

Re: Reading and Writing Tables to Files

by octacian » Tue Jun 21, 2016 17:58

I tried a method much like the one you showed, but I don't seem to get the return table properly.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
-- write table to file
function servertools.write_table(path, table)
  local table = minetest.serialize(table) -- serialize table
  local f = io.open(path, "w") -- open file for writing
  f:write(table) -- write table
  f:close() -- close file
  servertools.log("Wrote table to "..path)
end

-- load table from file
function servertools.load_table(path)
  local f = io.open(path, "r") -- open file for reading
  local table = f:read()
  f:close() -- close file
  return table
end

my_table = { foo = "bar" }

st.log("beginning file creation")
servertools.create_file(st.modpath.."/my_table")
servertools.write_table(st.modpath.."/my_table", my_table)
servertools.load_table(st.modpath.."/my_table")
st.log("file creation done and file read")


st.log("Original Table: "..my_table.foo)
if table then st.log("table detected: "..table.foo) end


After loading the table, if I try to print table.foo, I get nil. However, if I print my_table.foo I get bar. Somehow it doesn't seem as though the table is being returned properly, but I'm not sure why.
God isn't dead!

My Coolest Mods:
MicroExpansion, Working Computers, Interchangeable Hands

Check out my YouTube channel! (octacian)
 

Byakuren
Member
 
Posts: 441
Joined: Tue Apr 14, 2015 01:59
GitHub: raymoo
IRC: Hijiri

Re: Reading and Writing Tables to Files

by Byakuren » Tue Jun 21, 2016 18:59

endev15 wrote:I tried a method much like the one you showed, but I don't seem to get the return table properly.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
-- write table to file
function servertools.write_table(path, table)
  local table = minetest.serialize(table) -- serialize table
  local f = io.open(path, "w") -- open file for writing
  f:write(table) -- write table
  f:close() -- close file
  servertools.log("Wrote table to "..path)
end

-- load table from file
function servertools.load_table(path)
  local f = io.open(path, "r") -- open file for reading
  local table = f:read()
  f:close() -- close file
  return table
end

my_table = { foo = "bar" }

st.log("beginning file creation")
servertools.create_file(st.modpath.."/my_table")
servertools.write_table(st.modpath.."/my_table", my_table)
servertools.load_table(st.modpath.."/my_table")
st.log("file creation done and file read")


st.log("Original Table: "..my_table.foo)
if table then st.log("table detected: "..table.foo) end


After loading the table, if I try to print table.foo, I get nil. However, if I print my_table.foo I get bar. Somehow it doesn't seem as though the table is being returned properly, but I'm not sure why.


A couple issues:
  • server_tools.load_table returns the serialized table, rather than the actual table. You need to deserialize it first.
  • table (on the printing line) isn't defined in this code snippet, but I'll assume you defined it earlier since you said "nil" gets printed out rather than nothing.
  • table is never assigned to the table read from the file. When you call server_tools.load_table, you never assign the result to anything.
Every time a mod API is left undocumented, a koala dies.
 

User avatar
octacian
Member
 
Posts: 408
Joined: Mon Dec 21, 2015 22:18
GitHub: octacian
IRC: octacian
In-game: octacian

Re: Reading and Writing Tables to Files

by octacian » Wed Jun 22, 2016 00:27

Whoops, the load file code was an older version.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
-- load table from file
function servertools.load_table(path)
  local f = io.open(path, "r") -- open file for reading
  local table = minetest.deserialize(f:read()) -- deserialize and read table
  f:close() -- close file
  return table
end


That should take care of serialization issues. When servertools.load_table is called, I thought I assigned and returned the result through table, in turn defined by:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local table = minetest.deserialize(f:read()) -- deserialize and read table
...
return table
God isn't dead!

My Coolest Mods:
MicroExpansion, Working Computers, Interchangeable Hands

Check out my YouTube channel! (octacian)
 

Byakuren
Member
 
Posts: 441
Joined: Tue Apr 14, 2015 01:59
GitHub: raymoo
IRC: Hijiri

Re: Reading and Writing Tables to Files

by Byakuren » Wed Jun 22, 2016 06:44

That's a local definition and is only available in its enclosing scope (the body of load_table). You should assign the result of load_table to a new local variable, somewhere it will be in scope when you use it (changing servertools.load_table(st.modpath.."/my_table") to local table = servertools.load_table(st.modpath.."/my_table") would work fine).

Also you might want to avoid using the variable name "table", even locally, since you won't be able to access the table module which is a global table also called "table". If you don't use the table libraries in you own code though, it doesn't matter too much, but might be confusing if someone reading your code mistakes your local "table" for the global "table".

Setting the global "table" variable will ruin it for everyone who uses the table library though, and in general you should avoid setting global variables other than one with the same name as your mod (usually a table containing things you want to expose publically).
Every time a mod API is left undocumented, a koala dies.
 


Return to Modding Discussion

Who is online

Users browsing this forum: No registered users and 15 guests

cron