How to set io.output() back to default output file? - lua

I am learning how work with files in Lua, and I came across a problem.
I know that:
io.output() allows me to specify the file that I will write output to.
The io.write() function simply gets a number of string arguments and writes them to the current output file.
io.close() then closes the file I am reading or writing on.
I first set io.output() to "myNewFile.txt" then I did io.write("Hello World!").
io.output("myNewFile.txt")
io.write("Hello World!")
This part worked well and myNewFile.txt got Hello World written to it.
Then I wrote io.close() to close the myNewFile.txt.
After that, I wrote io.write("Hello World!"), but I got an error:
C:\\Program Files\\lua\\lua54.exe: ...OneDrive\\Documents\\learning lua\\steve's teacher\\main.lua:9: default output file is closed stack traceback: \[C\]: in function 'io.write' ...OneDrive\\Documents\\learning lua\\steve's teacher\\main.lua:9: in main chunk \[C\]: in ?
I wanted io.write("Hello World!") to write Hello World in the terminal. I know can use print() but print() function adds extra characters like \n and things like that.
So my question is, how do I write Hello World in the terminal using io.write("Hello World!") in this situation?
I tried to search this error up on Google, but there weren't any results. I also tried joining many Discord servers, but I didn't get a proper response. I am a new developer to Lua so this all is really confusing to me.

After io.close() do a io.output(io.stdout) to set it back.
The clean way
local oldout = io.output() -- without argument returns actual output
io.output("file") -- set to a filename
-- do file operations here
-- use io.flush() where it is necessary
io.close() -- close file also do a flush()
io.output(oldout) -- set back to oldout ( normally io.stdout )
-- changing io.output() back should also close() and flush() the "file"
-- But better doublecheck this when using userdata without experience

Related

"function arguments expected near 'levelc'" when using LOVE

I'm currently trying to make a level loading system for a game.
function love.filedropped(file)
ofile=io.open(file:getFilename(),"r")
io.input(ofile)
file:close
levelc=io.read()
for i=1,levelc do
levels[i]=io.read()
print levels[i]
end
levelc should be the first line of the file, and file:getFilename is the file to open (path included) the project gives an error message on startup, and i've used a similar structure before, but for an output. The error is at line 30, which is the levelc=io.read().
I've tried changing the name of the file pointer (it was "f" before, now "ofile") and i've tried using io.read("*l") instead of io.read() but same result.
EDITS:
-this is a love.filedropped(file)
-i need to open other files from a .txt later and i don't really understand how do do that
The parameter given by love.filedropped is a DroppedFile.
In your case helpful could be File:lines().
For example:
function love.filedropped(file)
-- Open for reading
file:open("r")
-- Iterate over the lines
local i = 0
for line in file:lines() do
i = i + 1
levels[i] = line
print(i, levels[i]) -- Notice the parentheses missing in your code
end
-- Close the file
file:close()
end
Notice that love2d usually only allows reading/writing files within the save or working directory. Dropped files are an exception.
Unrelated to this answer but things I noticed in your code:
Use locals, oFile should be local
file:close() required parentheses as its a function call
Same for the print
The filedropped callback has no end
You mentioned reading other files too, to do so, you can either:
Use love.filesystem.newFile and a similar approach as before
The recommended one-liner love.filesystem.lines

Lua io.popen freezing after a while of reading a log file

I'm attempting to constantly read and parse a log file (Minecraft log file) by using io.popen in tandem with Ubuntu's tail command so that I can send some messages upon certain events.
Now, I have mostly everything working here, except one small issue. After a while of reading, the entire program just freezes.
Here is the relevant code:
-- Open the tail command, return a file handle for it.
local pop = io.popen(config.listen_command)
-- Simply read a single line, I've pulled this into its own
-- function so that if this ever needs changing I can do so
-- easily.
local function get_line()
logger:log(4, "READ LINE")
return pop:read("*l")
end
-- For each line in the log file, check if it matches any
-- of a list of patterns, return the matches and the
-- pattern information if so.
local function match_line()
local line = get_line()
logger:log(4, "Line: %s", line)
-- This all works, and I've tested that it's not freezing
-- here. I've just included it for completion of the call
-- -stack.
for event_type, data in pairs(config.message_patterns) do
for event_name, pattern in pairs(data) do
local matches = {line:match(pattern)}
if matches[1] then
return event_type, event_name, matches
end
end
end
end
-- The main loop, simply read a line and send a message
-- if there was a match.
logger:log(4, "Main loop begin.")
while true do
local event_type, event_name, matches = match_line()
-- ...
-- The rest of the code here is not relevant.
config.listen_command = "tail -F --lines=1 latest.log"
The issue is in the get_line function. After a while of reading the log file, it completely freezes on the pop:read("*l"). It prints the READ LINE message, but never prints the Line: <whatever data here> line.
This is a really strange issue that I've been getting really confused about. I've tried swapping to different distributions of Lua (Luvit, LuaJIT, Lua) and a very large amount of debugging, changing small things, rerunning, ... But I cannot think of anything that'd be causing this.
Perhaps there's something small I've missed.
So my question here is this: Why is pop:read("*l") freezing, even though more data is being outputted to the logfile? Is there a way to fix this? Perhaps to detect if the next read will freeze indefinitely, so I can try closing the popen'ed file and re-open it (or to preferably stop it happening altogether?)

Unable to change to previous io input

i am currently trying to make a small script that temporarily changes the io input to a file and then back to the previews input. i have tried searching for solutions and all i found was this from lua.org
local temp = io.input() -- save current file
io.input("newinput") -- open a new current file
... -- do something with new input
io.input():close() -- close current file
io.input(temp) -- restore previous current file
however when i attempt this i get this error
Bad Argument #1 (string or file expected, got table):
i am relatively new to lua so any help would be outstanding
Thanks.

Getting return status AND program output

I need to use Lua to run a binary program that may write something in its stdout and also returns a status code (also known as "exit status").
I searched the web and couldn't find something that does what I need. However I found out that in Lua:
os.execute() returns the status code
io.popen() returns a file handler that can be used to read process output
However I need both. Writing a wrapper function that runs both functions behind the scene is not an option because of process overhead and possibly changes in result on consecutive runs. I need to write a function like this:
function run(binpath)
...
return output,exitcode
end
Does anyone has an idea how this problem can be solved?
PS. the target system rung Linux.
With Lua 5.2 I can do the following and it works
-- This will open the file
local file = io.popen('dmesg')
-- This will read all of the output, as always
local output = file:read('*all')
-- This will get a table with some return stuff
-- rc[1] will be true, false or nil
-- rc[3] will be the signal
local rc = {file:close()}
I hope this helps!
I can't use Lua 5.2, I use this helper function.
function execute_command(command)
local tmpfile = '/tmp/lua_execute_tmp_file'
local exit = os.execute(command .. ' > ' .. tmpfile .. ' 2> ' .. tmpfile .. '.err')
local stdout_file = io.open(tmpfile)
local stdout = stdout_file:read("*all")
local stderr_file = io.open(tmpfile .. '.err')
local stderr = stderr_file:read("*all")
stdout_file:close()
stderr_file:close()
return exit, stdout, stderr
end
This is how I do it.
local process = io.popen('command; echo $?') -- echo return code of last run command
local lastline
for line in process:lines() do
lastline = line
end
print(lastline) -- the return code is the last line of output
If the last line has fixed length you can read it directly using file:seek("end", -offset), offset should be the length of the last line in bytes.
This functionality is provided in C by pclose.
Upon successful return, pclose() shall return the termination status
of the command language interpreter.
The interpreter returns the termination status of its child.
But Lua doesn't do this right (io.close always returns true). I haven't dug into these threads but some people are complaining about this brain damage.
http://lua-users.org/lists/lua-l/2004-05/msg00005.html
http://lua-users.org/lists/lua-l/2011-02/msg00387.html
If you're running this code on Win32 or in a POSIX environment, you could try this Lua extension: http://code.google.com/p/lua-ex-api/
Alternatively, you could write a small shell script (assuming bash or similar is available) that:
executes the correct executable, capturing the exit code into a shell variable,
prints a newline and terminal character/string onto standard out
prints the shell variables value (the exit code) onto standard out
Then, capture all the output of io.popen and parse backward.
Full disclosure: I'm not a Lua developer.
yes , your are right that os.execute() has returns and it's very simple if you understand how to run your command with and with out lua
you also may want to know how many variables it returns , and it might take a while , but i think you can try
local a, b, c, d, e=os.execute(-what ever your command is-)
for my example a is an first returned argument , b is the second returned argument , and etc.. i think i answered your question right, based off of what you are asking.

Lua check if a file is open or not

I'm trying to script a lua file to check if a certain file is open. Then I want it to close that file if it is open. I know how to check if the file exist but I need to know how to check if the file is open, meaning the file is running.
Lua, like C, C++, and pretty much every other language, can only close files that it opens itself. You cannot close files open by other people (not with standard Lua calls); this would be incredibly rude.
So you can't test to see if a file is opened by someone else. Nor can you close their file. There may be system API calls you could make to do this, but you would have to give Lua scripts access to those APIs yourself. Lua's standard libraries can't do this.
Sounds like you want to check which if any programs have a given file open.
first thing that comes to mind is parsing the output of lsof on linux.
fd = io.popen("lsof path/to/my/file")
fileopened = (#fd:read("a*") > 0)
Kind of a hacky way to do it, but it works:
processname = "process_name_here.exe"
filedata = io.popen("tasklist /NH /FO CSV /FI \"IMAGENAME eq "..processname.."\"")
output = filedata:read()
filedata:close()
if output ~= "INFO: No tasks are running which match the specified criteria." then
-- Program is running. Close the program
os.execute("taskkill -im "..processname)
else
-- Program is not running
end
Just make sure to replace "process_name_here.exe" with the process name that shows up in task manager
Alternatively you can just use this to close it without checking if it was actually running:
os.execute("taskkill -im process_name_here.exe")

Resources