How can I check if a file exists using Lua?
Try
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
but note that this code only tests whether the file can be opened for reading.
Using plain Lua, the best you can do is see if a file can be opened for read, as per LHF. This is almost always good enough. But if you want more, load the Lua POSIX library and check if posix.stat(path) returns non-nil.
Lua 5.1:
function file_exists(name)
local f = io.open(name, "r")
return f ~= nil and io.close(f)
end
I will quote myself from here
I use these (but I actually check for the error):
require("lfs")
-- no function checks for errors.
-- you should check for them
function isFile(name)
if type(name)~="string" then return false end
if not isDir(name) then
return os.rename(name,name) and true or false
-- note that the short evaluation is to
-- return false instead of a possible nil
end
return false
end
function isFileOrDir(name)
if type(name)~="string" then return false end
return os.rename(name, name) and true or false
end
function isDir(name)
if type(name)~="string" then return false end
local cd = lfs.currentdir()
local is = lfs.chdir(name) and true or false
lfs.chdir(cd)
return is
end
os.rename(name1, name2) will rename name1 to name2. Use the same name and nothing should change (except there is a badass error). If everything worked out good it returns true, else it returns nil and the errormessage. If you dont want to use lfs you cant differentiate between files and directories without trying to open the file (which is a bit slow but ok).
So without LuaFileSystem
-- no require("lfs")
function exists(name)
if type(name)~="string" then return false end
return os.rename(name,name) and true or false
end
function isFile(name)
if type(name)~="string" then return false end
if not exists(name) then return false end
local f = io.open(name)
if f then
f:close()
return true
end
return false
end
function isDir(name)
return (exists(name) and not isFile(name))
end
It looks shorter, but takes longer...
Also open a file is a it risky
Have fun coding!
If you're using Premake and LUA version 5.3.4:
if os.isfile(path) then
...
end
For sake of completeness: You may also just try your luck with path.exists(filename). I'm not sure which Lua distributions actually have this path namespace (update: Penlight), but at least it is included in Torch:
$ th
______ __ | Torch7
/_ __/__ ________/ / | Scientific computing for Lua.
/ / / _ \/ __/ __/ _ \ | Type ? for help
/_/ \___/_/ \__/_//_/ | https://github.com/torch
| http://torch.ch
th> path.exists(".gitignore")
.gitignore
th> path.exists("non-existing")
false
debug.getinfo(path.exists) tells me that its source is in torch/install/share/lua/5.1/pl/path.lua and it is implemented as follows:
--- does a path exist?.
-- #string P A file path
-- #return the file path if it exists, nil otherwise
function path.exists(P)
assert_string(1,P)
return attrib(P,'mode') ~= nil and P
end
If you are willing to use lfs, you can use lfs.attributes. It will return nil in case of error:
require "lfs"
if lfs.attributes("non-existing-file") then
print("File exists")
else
print("Could not get attributes")
end
Although it can return nil for other errors other than a non-existing file, if it doesn't return nil, the file certainly exists.
An answer which is windows only checks for files and folders, and also requires no additional packages. It returns true or false.
io.popen("if exist "..PathToFileOrFolder.." (echo 1)"):read'*l'=='1'
io.popen(...):read'*l' - executes a command in the command prompt and reads the result from the CMD stdout
if exist - CMD command to check if an object exists
(echo 1) - prints 1 to stdout of the command prompt
An answer which is windows only checks for files and folders, and also requires no additional packages. It returns true or false.
You can also use the 'paths' package. Here's the link to the package
Then in Lua do:
require 'paths'
if paths.filep('your_desired_file_path') then
print 'it exists'
else
print 'it does not exist'
end
Not necessarily the most ideal as I do not know your specific purpose for this or if you have a desired implementation in mind, but you can simply open the file to check for its existence.
local function file_exists(filename)
local file = io.open(filename, "r")
if (file) then
-- Obviously close the file if it did successfully open.
file:close()
return true
end
return false
end
io.open returns nil if it fails to open the file. As a side note, this is why it is often used with assert to produce a helpful error message if it is unable to open the given file. For instance:
local file = assert(io.open("hello.txt"))
If the file hello.txt does not exist, you should get an error similar to stdin:1: hello.txt: No such file or directory.
For library solution, you can use either paths or path.
From the official document of paths:
paths.filep(path)
Return a boolean indicating whether path refers to an existing file.
paths.dirp(path)
Return a boolean indicating whether path refers to an existing directory.
Although the names are a little bit strange, you can certainly use paths.filep() to check whether a path exists and it is a file. Use paths.dirp() to check whether it exists and it is a directory. Very convenient.
If you prefer path rather than paths, you can use path.exists() with assert() to check the existence of a path, getting its value at the same time. Useful when you are building up path from pieces.
prefix = 'some dir'
filename = assert(path.exist(path.join(prefix, 'data.csv')), 'data.csv does not exist!')
If you just want to check the boolean result, use path.isdir() and path.isfile(). Their purposes are well-understood from their names.
If you use LOVE, you can use the function love.filesystem.exists('NameOfFile'), replacing NameOfFile with the file name.
This returns a Boolean value.
How about doing something like this?
function exist(file)
local isExist = io.popen(
'[[ -e '.. tostring(file) ..' ]] && { echo "true"; }')
local isIt = isExist:read("*a")
isExist:close()
isIt = string.gsub(isIt, '^%s*(.-)%s*$', '%1')
if isIt == "true" then
return true
end
return false
end
if exist("myfile") then
print("hi, file exists")
else
print("bye, file does not exist")
end
if you are like me exclusively on Linux, BSD any UNIX type you can use this:
function isDir(name)
if type(name)~="string" then return false end
return os.execute('if [ -d "'..name..'" ]; then exit 0; else exit 1; fi')
end
function isFile(name)
if type(name)~="string" then return false end
return os.execute('if [ -f "'..name..'" ]; then exit 0; else exit 1; fi')
end
Actually this looks even better:
function isDir(name)
if type(name)~="string" then return false end
return os.execute('test -d '..name)
end
function isFile(name)
if type(name)~="string" then return false end
return os.execute('test -f '..name)
end
function exists(name)
if type(name)~="string" then return false end
return os.execute('test -e '..name)
end
IsFile = function(path)
print(io.open(path or '','r')~=nil and 'File exists' or 'No file exists on this path: '..(path=='' and 'empty path entered!' or (path or 'arg "path" wasn\'t define to function call!')))
end
IsFile()
IsFile('')
IsFIle('C:/Users/testuser/testfile.txt')
Looks good for testing your way. :)
Related
function saveScore()
local path = system.pathForFile("scoredata001.txt", system.DocumentsDirectory)
local file = io.open(path, "w")
if file then
local score=get_score() --The get_score() returns the value of current score which is saved in 'score'.
local newScore = compareScore()
local contents = tostring( newScore )
file:write( contents )
io.close( file )
return true
else
print("Error: could not write Score")
return false
end
end
function loadScore()
local path = system.pathForFile("scoredata001.txt", system.DocumentsDirectory)
local contents = ""
local file = io.open( path, "r" )
if file then
local contents = file:read( "*a" )
local score = tonumber(contents);
io.close( file )
return score
end
print("Could not read scores from scoredata.txt")
return nil
end
function return_highScore()
local highscore=loadScore()
if highscore==nil then
highscore=0
end
return highscore
end
function compareScore()
local highscore=return_highScore()
if highscore then
local currscore=get_score()
if highscore==0 then
return highscore
elseif currscore>highscore then
return currscore
end
end
return true
end
function disp_permScore()
local display_score=return_highScore()
text_display2= display.newText("GAME OVER!\n BEST: " ..display_score, 0, 0, "Helvetica", 80)
text_display2.x = centerX
text_display2.y = centerY
text_display2.alpha=1
function gameOver()
mainScreen()
saveScore()
disp_permScore()
end
(This is with refernce to previous question Permission issues in lua )
Basically I'm trying to build a game in lua (This is my first ever game)
But, I'm unable to save highscore to file. If it gets saved, then I'm unable to retrieve them. (In short, I always some or the other error/problem in executing the code.
Please have a look at the code above. I want to display both high score and current score. Current score is being displayed perfect. This is something I tried yesterday night. But now, the high score is not being saved in file. (i.e. the best always displays 0) Also, the cmd says "unable to read scores form scoredata.txt) I'm unable to find where I went wrong.
Please help with this?
Please tell where do I go wrong?
Also, if possible, provide (or edit) the correct code please?
There seems to be a problem on this line
if highscore==0
then
return highscore
Meaning you check if the highscore is 0 and if it is then you return it instead of the actual higher score.
Also, I don't know if your code was just pasting error, but without indenting your code it becomes really hard to read. Try and look again I indentet it and now the error becomes really easy to spot.
Here is a demo I modified to remove the module(..., package.seeall) statement. It works great, and I want to use the same idea in a Corona sdk project. I want to pass a value to an existing variable that I created in the demo. Thanks for any advice.
main.lua--------------------------------------------------
-- Load external library (should be in the same folder as main.lua)
local testlib = require("testlib")
testlib.testvar = 100 -- Trying to change the testvar value in external module
-- cache same function, if you call more than once
local hello = testlib.hello
-- now all future invocations are "fast"
hello()
-- This all works fine, but I need to change the value of testvar.
testlib.lua -----------------------------------------------------
local M = {}
local testvar = 0 -- I need to change the value of this variable as well as others later.
print("testvar=",testvar)
local function hello()
print ("Hello, module")
end
M.hello = hello
return M
In this case Your local testvar is private variable for Your module (testlib.lua).
You need to provide some setters/getters for that private variable.
Basic example would be adding this to Your testlib.lua:
function setter(new_val)
test_var = new_val
end
function getter()
return test_var
end
M.set = setter
M.get = getter
Now, You can use testlib.set("some new value..") and print(testlib.get()) in Your main.lua to operate the value of testvar variable.
Situation :
There are two sensors and I want to save the data of values of each sensor in the certain file..But it's not working. I am working on linux system and the file is still empty.
What's wrong with my code? any suggestion please?
my code is:
--Header file
require("TIMER")
require("TIMESTAMP")
require("ANALOG_IN")
function OnExit()
print("Exit code...do something")
end
function main()
timer = "TIMER"
local analogsensor_1 = "AIR_1"
local analogsensor_2 = "AIR_2"
local timestr = os.data("%Y-%m-%d %H:%M:%S")
-- open the file for writing binary data
local filehandle = io.open("collection_of_data.txt", "a")
while true do
valueOfSensor_1 = ANALOG_IN.readAnalogIn(analogsensor_1);
valueOfSensor_2 = ANALOG_IN.readAnalogIn(analogsensor_2);
if (valueOfSensor_1 > 0 and valueOfSensor_2 > 0) then
-- save values of sensors
filehandle:write(timestr, " -The Value of the Sensors: ", tostring(valueOfSensor_1), tostring(valueOfSensor_2)"\n");
end
TIMER.sleep(timer,500)
end
-- close the file
filehandle:close()
end
print("start main")
main()
I do not know what this libs realy do.
But this code is incorrect;
1) you do not close while statement.
if in real code you close it before filehandle:close() then try call filehandle:flush()
2) you forgot comma:
filehandle:write(timestr, " -The Value of the Sensors: ", tostring(valueOfSensor_1), tostring(valueOfSensor_2)"\n")
(it should seay something like attemt call a number value).
3) try print out valueOfSensor_1 and valueOfSensor_2 values. May be there no data.
Beside the typos pointed out by #moteus, shouldn't this:
if (valueOfSensor_1 and valueOfSensor_2 > 0) then
be like this?
if (valueOfSensor_1 > 0 and valueOfSensor_2 > 0) then
Edit, in response to your comment to another answer:
still error..it says "attempt to call field 'data' (a nil value)
I can't be sure without the stack trace, but, most likely, something bad happens in the ANALOG_IN library code. You may not be using it properly.
try to turn this:
valueOfSensor_1 = ANALOG_IN.readAnalogIn(analogsensor_1);
valueOfSensor_2 = ANALOG_IN.readAnalogIn(analogsensor_2);
into this:
success, valueOfSensor_1 = pcall(ANALOG_IN.readAnalogIn, analogsensor_1);
if not success then
print("Warning: error reading the value of sensor 1:\n"..valueOfSensor_1)
valueOfSensor_1 = 0
end
success, valueOfSensor_2 = pcall(ANALOG_IN.readAnalogIn, analogsensor_2);
if not success then
print("Warning: error reading the value of sensor 2:\n"..valueOfSensor_2)
valueOfSensor_2 = 0
end
If the failure in ANALOG_IN is not systematic, it will work around it. If the call fails systematically, you'll get a huge warning log, and an empty collection_of_data.txt.
Please note that ANALOG_IN is not a standard Lua library. You should check its documentation , and pay attention to the details of its usage.
i have wrote the next lua module:
--mod.lua
local M = {}
function M.bar()
print "bar"
end
return M
And i'm trying to use it on another lua script as:
--main.lua
function Main(context)
local mod = require 'mod'
mod.bar()
end
But i am getting the error : "attempt to index ? (a boolean value)" on the line "mod.bar()"
The same result is obtained if i use module(..., package.seeall) on the header of mod.lua.
Could anybody help me?
Thanks to W.B. my 'mod.lua' was in another path. Sorry for wasting your time.
I've read PIL and the ModulesTutorial on creating modules but I'm having trouble require()ing them correctly.
Here is my setup:
-- File ./lib/3rdparty/set.lua
local ipairs = ipairs
module( "set" )
function newSet (t)
local set = {}
for _, l in ipairs(t) do set[l] = true end
return set
end
And:
-- File ./snowplow.lua
local set = require( "lib.3rdparty.set" )
module( "snowplow" )
local SUPPORTED_PLATFORMS = set.newSet { "pc", "tv", "mob", "con", "iot" }
Then if I run snowplow.lua:
lua: snowplow.lua:4: attempt to index local 'set' (a boolean value)
stack traceback:
snowplow.lua:4: in main chunk
[C]: ?
What am I doing wrong in my module definition - what is the boolean exactly? Also, if I append a return _M; at the bottom of my set.lua, then everything starts working - why?
true is usually returned by require if module function is not used inside module and module code doesn't return a value.
But anyway it seems strange.
-- file m0.lua
module'm0'
--file dir1\m1.lua
module'm1'
--file test.lua
print(require'm0')
print(m0)
print(require'dir1.m1')
print(m1)
for k,v in pairs(package.loaded) do
if k:match'm%d' then print(k, v) end
end
--output
table: 0036C8C8
table: 0036C8C8
true
table: 0036B6B0
m0 table: 0036C8C8
m1 table: 0036B6B0
dir1.m1 true
So, you can simply use global variable set instead of local set assigned a value returned by require.
UPD :
It is recommended to avoid using module function and always return your table at the end of your module. In that case the whole picture is just fine:
-- file m0.lua
return 'string0'
--file dir1\m1.lua
return 'string1'
--file test.lua
print(require'm0')
print(m0)
print(require'dir1.m1')
print(m1)
for k,v in pairs(package.loaded) do
if k:match'm%d' then print(k, v) end
end
--output
string0
nil
string1
nil
m0 string0
dir1.m1 string1
UPD2 :
Problem disappears if you replace module( "set" ) with module('lib.3rdparty.set').
So, each module must remember its relative path.
Now you could access it either by calling require'lib.3rdparty.set' or by reading global variable lib.3rdparty.set - the result would be the same.
require("lib.moduleName")
local moduleName = moduleName
I'm not sure why Lua returns a boolean when you require a module on a different directory, but it seems the module is correctly set on the the global variable. So I simply used that and put it on a local variable with the same name.