Corsaka
Corsaka

Reputation: 422

Prevent a file being written to more than once without file:close()

I'm currently working on a logging system. My problems arise when using for loops and file writing. Here is a small example:

file = io.open("text.txt","a") --text.txt can be literally anything
for i=1,8 do
  if x == true then
    file:write("X is true.")
  elseif y == true then
    file:write("Y is true.")
  end
end

Is there a way to stop the file from being written to multiple times without using file:close()? I have a huge number of different file:write sections, and adding file:close() after all of them would be a massive problem.

Upvotes: 0

Views: 113

Answers (3)

Corsaka
Corsaka

Reputation: 422

For my specific case, I've found a solution - since I just want a single option to print, and it's the last option (rather than the first, and I should've specified this), I can just set a variable to what I want my output to be and write that at the end.

log = ""
if x == 2 then
  log = "X is 2."
elseif y == 2 then
  log = "Y is 2."
end
file:write(log)

For the last option, I'd refer anyone to the accepted answer which should be perfect.

Upvotes: 0

IsawU
IsawU

Reputation: 450

If file:close() every time is a massive problem, then this is the custom logic you need.

myFileMetatable = {}  --implement all necessary file operations here
function myFileMetatable.write(self, str)
    if not self.written then
        self.written = true
        self.f:write(str)
    end
end
function myFileMetatable.close(self)
    self.f:close()
end

myFile = {}
function myFile.open(filename, mode)
    local t = {f = io.open(filename, mode)}
    setmetatable(t, {__index = myFileMetatable})
    return t
end

--now you can do
file = myFile.open("test", "w")
file:write("test")
file:write("hello")
file:write("world")
file:close()    --and only "test" will be written

Note that this is probably much better than replacing file:write(str) with something file_write(file, str), since you need to store somewhere the fact that the file has already been written to, which you cannot store inside the FILE* object and using a global variable for that will break when using multiple files. That's why I wrap the FILE* object in a table and use myFileMetatable to implement my own methods that I will need.

However, if you need just one file at a time and don't mind the global variable then this is more efficient.

file_written = false
function file_write(file, str)
    if not file_written then
        file_written = true
        file:write(str)
    end
end

file = io.open("test", "w")
file_write(file, "test")
file_write(file, "hello")
file_write(file, "world")
file:close()

Mind that it's not as pretty as the first example and you might face a problem in the future, if you decide to expand beyond one file.

Upvotes: 2

csaar
csaar

Reputation: 560

How Egor Skriptunoff already said, I'll recommend you to write your own writing function. I'm normally using sth. like this:

local function writeFile(filePath, str)
  local outfile = io.open(filePath, 'w')
  outfile:write(str)
  outfile:close()
end

For appending to the file easily change the mode from w to a.

Upvotes: 1

Related Questions