--//////////////////////////////////////////////////////// --//Everything you need to: --// save strings and tables --// load strings and tables --// verify/make files and paths --//------------------------- --///by ßottledHatê\\\ --// resources: --// http://www.lua.org/manual/4.0/manual.html#6.4 --// http://www.lua.org/manual/5.0/manual.html#5.6 --//------------------------- --// paths may be absolute: "c:\\path\\to\\a dir\\file.txt" --// relative to current dir: "scripts/save data/savefile.txt" --// UNC(network) paths use "\\\\pcname\\share\\this folder\\file.txt" --only if proper rights exist.. ;) --//------------------------- --//------------------------- --//VERIFY FILE (make) --//------------------------- --///verifyFile()\\\ --// make file and path(s) --// can used to verify a save/load file at start to prevent read/write errors --// when the verify funtion is used no changes are made to the file if it exists. a blank file with no data is created otherwise. --// optional returns: 1 file exists.. 2 on success new file made returns.. 0 on fail --// ...fails if path/filename is invalid to winblows. --// strip the function, put in main or at top of script to verify/make your global file at start. --//LUA5 / BCDC / DCDM function verifyFile(file) --//(make file) local f,e = io.open(file, "a+" ) if f then f:close() return 1 else local _,_,path = string.find(file, "(.+[/_\\]).+$") if path ~= nil then os.execute("mkdir ".."\""..gsub(path, "/", "\\").."\"") end f,e = io.open( file, "a+" ) if f then f:close() return 2 else return 0 end end end --//LUA4 / PTOKAX function verifyFile(file)--//(make file) local f,e = openfile( file, "a+" ) if f then closefile(f) return 1 else local _,_,path = strfind(file, "(.+[/_\\]).+$") if path ~= nil then execute("mkdir ".."\""..gsub(path, "/", "\\").."\"") end f,e = openfile( file, "a+" ) if f then closefile(f) return 2 else return 0 end end end --//verifFile() EXAMPLE. MySaveFile = "scripts/data/thisbot/settings.txt" x = verfyFile(MySaveFile) if x = 0 then --fail..path/filename is invalid to winblows elseif x = 1 --file exists. elseif x = 2 --file or path did not exist.. now they do. end --//------------------------- --//SAVE DATA .. (strings) --//------------------------- --///saveData()\\\ --// used to save a string to a file. --// will make file and path if they don't exist. --// optional returns: 1 data saved.. 2 data saved to new file.. returns.. 0 on fail --// ...fails if path/filename is invalid to winblows, or file locked to other process. --//LUA5 / BCDC / DCDM function saveData(file,string) local f,e = io.open(file, "a+" ) --// http://www.lua.org/manual/5.0/manual.html#5.6 <--more output options/ "a+" appends if f then f:write(string) f:close() return 1 else local _,_,path = string.find(crazyFileName, "(.+[/_\\]).+$") if path ~= nil then os.execute("mkdir ".."\""..gsub(path, "/", "\\").."\"") end f,e = io.open( file, "a+" ) if f then f:write(string) f:close() return 1 else --**yourGlobalFileName** = "_DefaultFileName"--//EDIT to your global and default filenames.(no path!) --saveData(**yourGlobalFileName**, string) --//for if you use the default filename... return 0 end end end --//LUA4 / PTOKAX function saveData(file, string) local f,e = openfile( file, "a+" )--// http://www.lua.org/manual/4.0/manual.html#6.4 <--more output options/ "a+" appends if f then write(f,string) closefile(f) return 1 else local _,_,path = strfind(sFileName, "(.+[/_\\]).+$") if path ~= nil then execute("mkdir ".."\""..gsub(path, "/", "\\").."\"") end f,e = openfile( sFileName, "a+" ) if f then write(f,string) closefile(f) return 2 else --**yourGlobalFileName** = "_DefaultFileName"--//EDIT to your global and default filenames.(no path!) --saveData(**yourGlobalFileName**, string) --//for if you use the default filename... return 0 end end end --//saveData() EXAMPLE. MySaveFile = "scripts/data/thisbot/settings.txt" MySaveData = "bleh blah bluh" x = saveData(MySaveFile, MySaveData) if x = 0 then --fail..path/filename is invalid to winblows elseif x = 1 --file exists. data saved... (in this case "a+" appends) elseif x = 2 --file or path did not exist.. now they do. data saved end --//------------------------- --//LOAD DATA .. (strings) --//------------------------- --///loadData()\\\ --// used to load an entire file to a string. --// returns files text as string, or nil on fail --//LUA5 / BCDC / DCDM function loadData(file) local tmp = "" local f,e = io.open(file,"r") if f then tmp = f:read("*a") f:close(f) return tmp else return nil end end --//LUA4 / PTOKAX function loadData(file) local tmp = "" local f,e = openfile(file,"r") if f then tmp = read(f,"*a") closefile(f) return tmp else return nil end end --//loadData() EXAMPLE. MySaveFile = "scripts/data/thisbot/settings.txt" MySavedData = loadData(MySaveFile) --//------------------------- --//SERIALIZE TABLES --//------------------------- --///Serialize()\\\ --// used to convert a table into a string for saving. this allows for quick easy reading back in. --// tTable = the table you want to save. sTableName = the tables name as a string. sTab = leave blank or "". --//LUA5 / BCDC / DCDM function Serialize(tTable, sTableName, sTab) sTab = sTab or ""; sTmp = "" sTmp = sTmp..sTab..sTableName.."={" local tStart = 0 for key, value in tTable do if tStart == 1 then sTmp = sTmp..",\r\n" else sTmp = sTmp.."\r\n" tStart = 1 end local sKey = (type(key) == "string") and string.format("[%q]",key) or string.format("[%d]",key); if(type(value) == "table") then sTmp = sTmp..SerializeCrazy(value, sKey, sTab.."\t"); else local sValue = (type(value) == "string") and string.format("%q",value) or tostring(value); sTmp = sTmp..sTab.."\t"..sKey.." = "..sValue end end sTmp = sTmp.."\r\n"..sTab.."}" return sTmp end --//LUA 4 / PTOKAX function Serialize(tTable, sTableName, sTab) sTab = sTab or ""; sTmp = "" sTmp = sTmp..sTab..sTableName.."={" local tStart = 0 for key, value in tTable do if tStart == 1 then sTmp = sTmp..",\r\n" else sTmp = sTmp.."\r\n" tStart = 1 end local sKey = (type(key) == "string") and format("[%q]",key) or format("[%d]",key); if(type(value) == "table") then sTmp = sTmp..Serialize(value, sKey, sTab.."\t"); else local sValue = (type(value) == "string") and format("%q",value) or tostring(value); sTmp = sTmp..sTab.."\t"..sKey.." = "..sValue end end sTmp = sTmp.."\r\n"..sTab.."}" return sTmp end --//Serialize() EXAMPLE. --// this example will cover converting the table with Serialize, saveing with saveData, then loading with dofile. MyTable = {["bleh"] = 1, ["bloop"] = {["bloop1"] = "bleeeep1", ["bloop2"] = "bleeeep2"}} MySaveFile = "scripts/data/thisbot/settings.txt" MySaveData = Serialize(MyTable, "MyTable", "") -- the second argument determines the name of the table when read back in. x = saveData(MySaveFile, MySaveData) if x = 0 then --fail..path/filename is invalid to winblows elseif x = 1 --file exists. data saved... (in this case "a+" appends) elseif x = 2 --file or path did not exist.. now they do. data saved end --//ok, so the file is all saved now.. and the script is restarting due to whatever reason.. --to load the table back into the script... x = verifyFile(MySaveFile) if x = 0 then --fail..path/filename is invalid to winblows elseif x = 1 dofile(MySaveFile) --loads the table into the scipt, with the name being the second argument passed to serialize.. in this case "MyTable" (no change) --file exists. elseif x = 2 --file or path did not exist.. now they do. --//rebuild your blank tables static values! end --// so why verify then dofile? --// because if the file did not exist. then there is no tabel data. and if you have static vaules in the table.. --// when your script tries to access them it will error out. so you would wnat to built the blank table there. --// think of it as first run and someone new is using your script, so they don't have save data file yet... --// meaning there is nothing to load in... --//------------------------- --//Load TABLES (that were serialized) --//------------------------- --// loading tables that were serialized is the quickest and easiest way to load saved data. (that i have found) --// the only thing needed is dofile. --// i usually verify the file before doing the dofile to make sure there are no errors. --//LUA 4 / LUA 5 dofile("yourfilename") --//dofile() EXAMPLE. --see example for Serialize for dofile. --//------------------------- --//RANDOM functions for files i've made... --//------------------------- --//Remove a line number from a file. --// with a lil moding this function can easily, add data before/after/on a line number.. read line number, and more. --// LUA 5 function removeLine(file,rline) local lineN = 1 local tmp ="" for line in io.lines(filename) do if lineN ~= rline then tmp = tmp..line.."\r\n" end lineN = lineN +1 end local f,e = io.open( filename, "w+" ) --// http://www.lua.org/manual/5.0/manual.html#5.6 <--more output options/ "w+" overwrites. if f then f:write( tmp ) f:close() end end --//LUA 4 function removeLine(file,rline) local lineN,tmp = 1, "" readfrom(file) while 1 do local line = read() if line == nil then break else if lineN ~= rline then tmp = tmp..line.."\n" end lineN = lineN + 1 end end readfrom() local f,e = openfile(file, "w+" ) --//... "w+" overwrites if f then write(f,tmp) closefile(f) end end --//load DC++ favorite users into talble (LUA5 BCDC / DCDM only) --// easily modded to do other things. --// returns a table in the format {["nick1"] = 1, ["nick2"] = 1, ["nick3"] = 1, ... } ...so the names are hashed function loadFavUsers() local start=0 local favUsers={} for line in io.lines("Favorites.xml") do if string.find(line, "") then return favUsers break end if start ==1 then local s,e,favnick = string.find(line, "") then start=1 end end --//This is the end... for now... i hope you were able --// to learn something from this file. more file manipulation --// to come! requests welcomed. --///BH\\\ --////////////////////////////////////////////////////////