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.
Related
I've got this program that starts off with the program grabbing a file's contents.
local oldprint = print
local print = io.write
-- this was done mainly because the newline from print() wasn't needed
io.input("script.txt")
local script = io.read("*all")
io.close()
Then there is a function containing another io.read(), which should allow for the user's input.
local functions = {
[","] = function()
local input
repeat
print("\nAwaiting input... (must be a number)\n")
input = io.read("*n")
until input ~= nil
array[pointer] = input
print(stringy)
end
}
functions[","]()
I expect it for it to print once, and then grab the input, but it ends up constantly printing.
I've tried using io.flush(), but it didn't work, and I'm not exactly sure what else to try...
By calling io.input("script.txt") you set that file as the default input file. Any following calls to io.read() will hence read from that file.
Either use file:read instead of io.read or reset the input to the standard input stream by calling io.input(io.stdin).
I suggest you refer to the Lua reference manual.
https://www.lua.org/manual/5.4/manual.html#6.8
To use io.read(), you have to close the file you opened, because if you have a file open, lua will assume you are reading from the file that you opened.
Try grabbing the input before you open the file
I typed up my code not expecting it to work first try, and of course it didn't. I kept tweaking it for hours on end, but I kept getting the same result until I made as simple as possible.
local file = io.open("File_Name", "r")
io.output(file)
local test = io.read('*all')
io.close(file)
print(test)
After getting (no return) from this, I've decided to take a break and let someone else answer my question.
The problem with your code is that you're trying to read from whatever is defined as your input file. You only opened a file, but you didn't tell Lua to use it as the input file, so io.read won't read from the opened file, yet.
local file = io.open(filename, "r")
local test = file:read("a")
io.close(file)
print(test)
Alternatively:
local file = io.open(filename, "r")
io.input(file)
local test = io.read("a")
io.close(file)
print(test)
or
local file = io.open(filename, "r")
local test = io.input(file):read("a")
io.close(file)
print(test)
Of course you should check wether opening the file succeeded befor using the file handle.
Depending on your Lua version the read format is either *a or a. I cannot remember if both is ok in all versions. At least that's what the manual says.
I am learning the Lua IO library. I'm having trouble with io.write(). In Programming Design in Lua, there is a piece of code that iterates through the file line by line and precedes each line with a serial number.
This is the file I`m working on:
test file: "iotest.txt"
This is my code
io.input("iotest.txt")
-- io.output("iotest.txt")
local count = 0
for line in io.lines() do
count=count+1
io.write(string.format("%6d ",count), line, "\n")
end
This is the result of the terminal display, but this result cannot be written to the file, whether I add IO. Output (" iotest.txt ") or not.
the results in terminal
This is the result of file, we can see there is no change
The result after code running
Just add io.flush() after your write operations to save the data to the file.
io.input("iotest.txt")
io.output("iotestout.txt")
local count = 0
for line in io.lines() do
count=count+1
io.write(string.format("%6d ",count), line, "\n")
end
io.flush()
io.close()
Refer to Lua 5.4 Reference Manual : 6.8 - Input and Output Facilities
io.flush() will save any written data to the output file which you set with io.output
See koyaanisqatsi's answer for the optional use of file handles. This becomes especially useful if you're working on multiple files at a time and gives you more control on how to interact with the file.
That said you should also have different files for input and output. You'll agree that it doesn't make sense to read and write from and to the same file alternatingly.
For writing to a file you need a file handle.
This handle comes from: io.open()
See: https://www.lua.org/manual/5.4/manual.html#6.8
A file handle has methods that acts on self.
Thats the function after the : at file handle.
So io.write() puts out on stdout and file:write() in a file.
Example function that can dump a defined function to a file...
fdump=function(func,path)
assert(type(func)=="function")
assert(type(path)=="string")
-- Get the file handle (file)
local file,err = io.open(path, "wb")
assert(file, err)
local chunk = string.dump(func,true)
file:write(chunk)
file:flush()
file:close()
return 'DONE'
end
Here are the methods, taken from io.stdin
close = function: 0x566032b0
seek = function: 0x566045f0
flush = function: 0x56603d10
setvbuf = function: 0x56604240
write = function: 0x56603e70
lines = function: 0x566040c0
read = function: 0x56603c90
This makes it able to use it directly like...
( Lua console: lua -i )
> do io.stdout:write('Input: ') local result=io.stdin:read() return result end
Input: d
d
You are trying to open the same file for reading and writing at the same time. You cannot do that.
There are two possible solutions:
Read from file X, iterate through it and write the result to another file Y.
Read the complete file X into memory, close file X, then delete file X, open the same filename for writing and write to it while iterating through the original file (in memory).
Otherwise, your approach is correct although file operations in Lua are more often done using io.open() and file handles instead of io.write() and io.read().
I'm trying to make a Discord bot with lua and its going well so far, but I'm having a couple problems with the IO portion of lua.
I'm trying to read a large list.txt file in lua and inserting each line into a table, but so far all of my attempts didn't work.
Any advice?
Attempt #1 spits out nil:
local open = io.open
local function read_file(path)
local file = open(path, "r") -- r read mode and b binary mode
if not file then return nil end
local content = file:read "*a" -- *a or *all reads the whole file
file:close()
return content
end
local fileContent = read_file("list.txt")
local vga_files = {}
table.insert(vga_files, fileContent)
I was not able to replicate your error running your code. Your code is valid, and is likely doing what you asked it to do.
here you tell the read_file function to return nil:
if not file then return nil end
So if the file is not found you will get nil. A good step in debugging would be to add a print in the body of this if statement and see if it is getting entered.
When you call read_file:
local fileContent = read_file("list.txt")
you pass in only a file name, this means lua will look for that where ever the code is being executed, and this location maybe different from what you expect.
I validated your code works by pointing the read at itself, and printing the result.
local open = io.open
local function read_file(path)
local file = open(path, "r") -- r read mode and b binary mode
if not file then return nil end
local content = file:read "*a" -- *a or *all reads the whole file
file:close()
return content
end
print(read_file("so_io_read_test.lua"))
Additionally to get the lines you should really used io.lines which creates an iterator that you can use in a for loop.
local vga_files = {}
for line in io.lines("list.txt") do
table.insert(vga_files, line)
end
Or alternatively you can read the file and then split the lines using gmatch.
local contents = read_file("so_io_read_test.lua")
for line in contents:gmatch("([^\n]+)") do
table.insert(vga_files, line)
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.