Read whole file and print in lua - lua

I am a complete beginner in Lua and only have a bit experience in C#.
At the moment I am usin ZeroBrane Studio as an IDE. I am trying to read a file and print the whole file to console like this:
function readAll(file)
local f = io.open(file, "rb")
local content = f:read("*all")
f:close()
return content
end
print(readAll("test.txt"))
but I get an error on line 8, which is local content = f:read("*all") with this message: attempt to index local 'f' (a nil value)
What is wrong with my code? I am explicitly not using the lines iterator here.
Btw. I also tried to use these answers by copy-pasting: How to read data from a file in Lua
Reading whole files in Lua
but no luck

The error message means that the file does not exist or cannot be opened.
Use local f = assert(io.open(file, "rb")) to see what error you get.
Or local f, err = io.open(file, "rb") and print or handle err if f == nil.

Related

Lua is refusing to read from a 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.

How to load host.conf file variables in lua script

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");

How to insert file lines into table in lua

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

Attempt to index local 'file' (a nil value)?

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

Lua not printing before file read

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.

Resources