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.
Related
I need to load configuration variables from .conf file in lua script, and use those variables to connect to a database. I have tried using:
require "host.conf"
loadfile("host.conf") - error with unexpected token '#'
os.execute("pathToConfFile/host.lua") - and I have created a lua host file with variables in bash shell
io.popen("host.conf") etc..
None of these solutions are valid.
Is there a way to use the existing host.conf file in lua, and avoid the unexpected token error?
Thank you for your suggestions.
local original = io .open('host.conf')
local hostconf = {} -- copy contents into Lua table
for line in original :lines() do
table .insert( hostconf, line )
end ; io .close( original )
print( hostconf[1] ) -- prints line 1
You haven't specified what format your host.conf comes in, but you'll likely want to parse it better than just throwing contents in a list. Perhaps splitting each line into head / tail, based upon a delimiter ( comma, space, whatever you have between variable & value )
Thank you to everyone who helped out. My question wasn't precise and I had more to learn before I have asked and sorry about that. This is what I used to solve the problem.
local open = io.open
local function read_file(path)
local file = open(path, "r")
if not file then return nil end
local content = file:read "*a" -- *a or *all reads the whole file
local lines = {}
for line in io.lines(path) do
--print(line);
if(line:find(var)~=nil)then
local varStart=string.len(var)+2
local varEnd=string.len(line)
var=string.sub(line,varStart,varEnd)
print(var);
end
--repeat for every line
end
file:close()
return lines;
end
local fileContent = read_file("path");
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 think the tile explains it self how do I access these files and read and write them?
this is what my code looks like
local openFile = assert(io.open(wasd_ ,"r")) -- wasd_ is the .txt file I want to open
local t = openFile:read("r") -- read the file
I'm not sure if in the 1st line of code if I shut replace "wasd_" with "wasd_.txt" or the file path (i.e replace wasd_ with something like this --> C:/users/stuff/blah/thing/wasd_)
ant help is greatly appreciated
According to the documentation:
local Filename = "wasd_.txt"
local File = io.open(Filename, "r")
local FileContent = File:read("*all")
File:close()
The file will be open according to the current directory %CD%. If your current directory is C:\test\, then the open file will be C:\test\wasd_.txt. If you want to find another file, you could specify the full path C:\users\stuff\blah\thing\wasd_.txt
you can do it all-at-once if you want; Lua allows that, but you have more control over editing when you do it line-at-a-time; in case you need to use certain edits on certain lines. It's also much safer to write to a new file, so you still have your original, to compare and try again, if need be.
line by line, keeping original, writing to new text
local path = 'C:/users/stuff/blah/thing/wasd_.txt' -- wasd_ is the .txt file I want to open
local newpath = path :sub( 1, -5 ) ..'new.txt' -- C:/users/stuff/blah/thing/wasd_new.txt
local iput = assert( io.input( path ) )
local oput = assert( io.output( newpath ) )
local linenum = 0 -- used as a counter
while true do
linenum = linenum +1
local line = iput :read()
if line == nil then break end -- break out of loop if there's nothing else to read
local newline, _ = line :gsub( 'this', 'that' ) -- do your changes here
if linenum == 1 then newline = 'HEADER: ' ..newline end -- example of specific line edit
oput :write( linenum ..' ' ..newline ..'\n' ) -- read() line strips newline char, so add it back
end
iput :close()
oput :close()
You can take out all instances of linenum if it's not needed, but I would strongly recommend that you use two separate read & write files, at least until you're comfortable it's doing exactly what you want, and has no errors.
I am trying to copy only latest file from a directory using lua file.
Latest file means : depends on modified time/created time.
How can i do this?
Referring to this question: How can I get last modified timestamp in Lua
You might be able to leverage the io.popen function to execute a shell command to get the name of the file. It seems like there's no builtin function that exposes filesystem metadata or stats. Something like this might work:
local name_handle = io.popen("ls -t1 | head -n 1")
local filename = name_handle:read()
I'm not familiar with Lua, but perhaps this helps. I imagine that once you have the name of the newest file you can use the other IO functions to do the copying.
local function get_last_file_name(directory)
local command = 'dir /a-d /o-d /tw /b "'..directory..'" 2>nul:'
-- /tw for last modified file
-- /tc for last created file
local pipe = io.popen(command)
local file_name = pipe:read()
pipe:close()
return file_name
end
local directory = [[C:\path\to\your\directory\]]
local file_name = get_last_file_name(directory)
if file_name then
print(file_name)
-- read the last file
local file = io.open(directory..file_name)
local content = file:read"*a"
file:close()
-- print content of the last file
print(content)
else
print"Directory is empty"
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.