I use:
file = io.open(path)
to open a file specified by the path. Now, after some actions, I would use file:close() to close the file but there are some times that I didn't even open a file to close it after. How can I check whether a file has been open or not?
hjpotter92 suggestion works, the condition is not always false:
> if file then print("File was opened") else print("What File?") end
What File?
> file = io.open("file.txt")
> if file then print("File was opened") else print("What File?") end
File was opened
> file:close()
> file = nil -- assign to nil after closing the file.
> if file then print("File was opened") else print("What File?") end
What File?
>
if you follow this pattern then closing only an open file is easy:
if math.random() < .5 then
file = open("file.txt") -- maybe it opened
end
if file then -- close only if opened
file:close()
file = nil
end
A file is open if and only if it exists (not nil).
It is very hard using standard Lua calls to check if a file is open, however if it is just one script accessing the file You could set a variable to True when you open the file and check for it before closing it.
You may find this page helpful:
Lua check if a file is open or not
Related
lets say you have a script like this
print("you've been here for the first time.")
print("you're here for second or more time")
how would you make it so once a person runs the script once, instead of repeating the whole script it just goes to the second print right away?
You basically need to:
Save the state of the program when the program ends
Restore the state of the program when the program starts
There are several ways to store the state, the simplest way would be to create a file and store the state inside. One could also use the Windows Registry, a database, a remote server, etc.
A simple example:
function FileExists (Filename)
local File = io.open(Filename, "r")
if File then
File:close()
end
return File
end
function CreateFile (Filename)
local File = io.open(Filename, "w")
if File then
File:close()
end
end
ProgramStateFile = "program-state.txt"
if not FileExists(ProgramStateFile) then
print("you've been here for the first time.")
else
print("you're here for second or more time")
end
CreateFile(ProgramStateFile)
In this example, the state is only the existence of the state file. Obviously, you can extend this example by writing additional information inside the file.
function ReadState (Filename)
local File = io.open(Filename, "r")
local State
if File then
State = File:read("a")
File:close()
end
return State
end
function WriteState (Filename, State)
local File = io.open(Filename, "w")
if File then
File:write(State)
File:close()
end
end
ProgramStateFile = "program-state.txt"
if ReadState(ProgramStateFile) ~= "PROGRAM-FINISHED" then
print("you've been here for the first time.")
else
print("you're here for second or more time")
end
WriteState(ProgramStateFile, "PROGRAM-FINISHED")
Finally, please note that there are many formats already existing to store the states: INI file, XML, JSON, etc. For Lua, you could also use a serialization library in order to store a Lua table directly inside a file. I would personally recommend the binser library.
I'm doing a project in corona simulator that involves reading some data in from a csv file ("car.csv") that is in the project directory, I have this code that is supposed to read the first line in, but when I run it it gives me the error "Attempt to index local 'file' (a nil value)". Any idea how I can fix this?
local function init()
local path = system.pathForFile( "car.csv", system.DocumentsDirectory );
local file = io.open(path, "r");
line = file:read();
print(line);
end
For some reason it won't read it in to 'file'.
Edit: Ok if I use the full path rather than the relative file path it works. But I need to use the relative one and I don't know why it doesn't work.
When using io.open, you should always make sure that it actually succeeded before trying to read the file, or you will get an ugly "attemp to index nil" error.
If you want your program to still crash, just do
local file = assert(io.open(path, 'r'))
And it will give you a more helpful error message if the file can't be found. Alternatively, you could also manualle save the return values of io.open and check for errors:
local file, err, code = assert(io.open(path))
if not file then
print("Error opening file", path, err)
-- Do something to handle the error
end
I'm working on a script for FoldingText which will convert a FoldingText outline (basically a Markdown Text file) into a Remark presentation (an HTML script which makes slideshows from Markdown files). The script works, but I'd like to make the following improvement:
Instead of asking for the name and location to save the HTML file, I'd like to grab the name of the current document and save it as an HTML file (with the same name) in the current folder. The script should fail nicely if there is already a document with that name (offering to either write-over the document or save as a new document with a different name).
The script I'm using for writing to the file was from these forums. The first part is:
on write_to_file(this_data, target_file, append_data) -- (string, file path as string, boolean)
try
set the target_file to the target_file as text
set the open_target_file to ¬
open for access file target_file with write permission
if append_data is false then ¬
set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof as «class utf8»
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
And the second part is:
set theFile to choose file name with prompt "Set file name and location:"
my write_to_file(finalText, theFile, true)
Thanks.
FoldingText should have some way of retrieveng the path of the document. I've not found any free dowonload fo the application, so I've not benn able to check by myself, but you should be able to find it if you view the dictionary of the application.
My guess is that there's a property like 'path of', or 'file of' for the FoldingText document:
You will probably end up with something like this:
set theDocPath to file of front document of application "FoldingText"
tell application "Finder"
set theContainer to container of theFile
end tell
set newPath to (theContainer & "export.html) as string
repeat while (file newPath exists)
set newPath to choose file name with prompt "Set file name and location:"
end repeat
my write_to_file(finalText, newPath, true)
I am new to corona and want to add a functionality in my app that on pressing back button, all data stored by the user get deleted from the documents directory. In short I want to know is there a way to empty documents directory?
Yes, you would use the LFS (Lua File System) module for that. See:
http://www.coronalabs.com/blog/2012/05/08/luafilesystem-lfs-tutorial/
Use this to delete all the files in /documents directory
local lfs = require "lfs";
local doc_dir = system.DocumentsDirectory;
local doc_path = system.pathForFile("", doc_dir);
local resultOK, errorMsg;
for file in lfs.dir(doc_path) do
local theFile = system.pathForFile(file, doc_dir);
if (lfs.attributes(theFile, "mode") ~= "directory") then
resultOK, errorMsg = os.remove(theFile);
if (resultOK) then
print(file.." removed");
else
print("Error removing file: "..file..":"..errorMsg);
end
end
end
I'm having an issue getting Lua to print before running a file open and read. This will print the strings "Reading File..." and "File Read!" but only after it has completed the getFileString() function. I want it to print "Reading File..." before it runs. I narrowed it down to file:read("*a") which is messing up all the prints in my (larger) script.
function getFileString(path)
local file, err = io.open(path, "r")
local all = file:read("*a")
file:close()
return all
end
function main()
local directory = "C:\\Documents and Settings\\All Users\\Documents\\"
print("Reading File...")
local file_all = getFileString(directory.."myFile.txt")
print("File Read!\n")
end
main()
It also didn't seem to matter whether I functionalised or not. I should mention that it's noticeable mainly as I am reading a 150MB or so file.
I think the output is simply buffered. Try adding io.stdout:setvbuf('no') before printing, which should turn buffering of output off.