0

I have a file with a large table. Need to open it, get certain values and replace other values with the new ones. With this example, Females and Males Classroom a and b must equal Teachers Classroom a and b. Read as much as I can on IO, but I cannot seem to get this to work correctly. Any help will be greatly appreciated.

--file with sample data to test, original file has 7000+lines
    theData = 
    {
        ["theSchool"] = 
            {
            ["theTeachers"] = 
            {
                ["theClassroom"] = 
                {
                    ["a"] = 001,
                    ["b"] = 002,
                    },
                },
                ["theFemales"] = 
                {
                    ["theClassroom"] = 
                    {   
                        ["a"] = 005,
                        ["b"] = 010,
                    },
                },
                ["theMales"] = 
                {   
                    ["theClassroom"] = 
                    {
                        ["a"] = 012,
                        ["b"] = 014,
                    },
                },
            },
    }

Then the function file looks like this

local file = io.open(filepath,'r')
local newCa = '["a"] = '..theData.theSchool.theTeachers.theClassroom.a
local newCb = '["b"] = '..theData.theSchool.theTeachers.theClassroom.b
local replaceFa = '["a"] = '..tostring(theData.theSchool.theFemales.theClassroom.a)
local replaceFb = '["b"] = '..tostring(theData.theSchool.theFemales.theClassroom.b)
local replaceMa = '["a"] = '..tostring(theData.theSchool.theMales.theClassroom.a)
local replaceMb = '["b"] = '..tostring(theData.theSchool.theMales.theClassroom.b)
file:close()
--Will it work?
print("Original Values:")
print(newCa)
print(newCb)
print(replaceFa)
print(replaceFb)
print(replaceMa)
print(replaceMb)
file = io.open(filepath,'r+')
function lines_from(filepath)
  lines = {}
  for line in io.lines(filepath) do 
    lines[#lines + 1] = line
  end
  return lines
end
local lines = lines_from(filepath)
for k,v in ipairs(lines) do
  if v == replaceFa then
    file:write(newCa..'\n')
  elseif v == replaceFb then
    file:write(newCb..'\n')
  elseif v == replaceMa then
    file:write(newCa..'\n')
  elseif v == replaceMb then
    file:write(newCb..'\n')
  else
    file:write(v..'\n')
  end
  --('[' .. k .. ']', v)
end
--replaceF = {[a] = newCa, [b] = newCb}
--replaceM = {[a] = newCa, [b] = newCb}
--file:write(replaceF)
--file:write(replaceM)
--print(tostring(theData.theSchool.theFemales.theClassroom.a))
file:close()
file = io.open(filepath,'r')
--Did it work?
print("New Values:")
print(theData.theSchool.theTeachers.theClassroom.a)
print(theData.theSchool.theTeachers.theClassroom.b)
print(theData.theSchool.theFemales.theClassroom.a)
print(theData.theSchool.theFemales.theClassroom.b)
print(theData.theSchool.theMales.theClassroom.a)
print(theData.theSchool.theMales.theClassroom.b)```

> I'll remove all the print things after it works.
DJ Lang
  • 1
  • 1

1 Answers1

1

try this solution, loading the table in one read of the file will be faster, and writing is also better with one command write

--- read
local handle = io.open("data.lua",'rb')
local data  = handle:read("*a")
handle:close()

data = data .. "\n return theData" 

local t = loadstring(data)()

-- edit
theData.theSchool.theTeachers.theClassroom.a = theData.theSchool.theTeachers.theClassroom.a + 1

-- write
local function concat(t, r)
     r = r or {}
     for k,v in pairs(t)  do
         if type(v)=="table" then
            r[#r+1] = string.format('\t["%s"]={\n',k  ) 
            concat(v, r)
            r[#r+1] = "\t},\n" 
         else 
            r[#r+1] = string.format('\t\t["%s"]=%03s,\n',k ,v ) 
         end
     end  
     return r    
end
local r = concat(t)
local text = "theData = { \n " .. table.concat(r) .. "}"
print(text) -- just control


local handle = io.open("data.lua",'wb')
local data  = handle:write(text)
handle:close()
Mike V.
  • 2,077
  • 8
  • 19
  • Appreciate the answer, thank you very much. I am however getting stuck on the loadstring line, even local t = assert(loadstring(data))() return nil value (global 'loadstring') – DJ Lang Oct 10 '20 at 07:17
  • [see here for example](https://stackoverflow.com/questions/37641153/loadstring-function-replacement-in-latest-version) - in lua 5.3 replaced with `load` – Mike V. Oct 10 '20 at 16:53