How to read data from a file in Lua - lua

I was wondering if there was a way to read data from a file or maybe just to see if it exists and return a true or false
function fileRead(Path,LineNumber)
--..Code...
return Data
end

Try this:
-- http://lua-users.org/wiki/FileInputOutput
-- see if the file exists
function file_exists(file)
local f = io.open(file, "rb")
if f then f:close() end
return f ~= nil
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function lines_from(file)
if not file_exists(file) then return {} end
local lines = {}
for line in io.lines(file) do
lines[#lines + 1] = line
end
return lines
end
-- tests the functions above
local file = 'test.lua'
local lines = lines_from(file)
-- print all line numbers and their contents
for k,v in pairs(lines) do
print('line[' .. k .. ']', v)
end

You should use the I/O Library where you can find all functions at the io table and then use file:read to get the file content.
local open = io.open
local function read_file(path)
local file = open(path, "rb") -- 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("foo.html");
print (fileContent);

Just a little addition if one wants to parse a space separated text file line by line.
read_file = function (path)
local file = io.open(path, "rb")
if not file then return nil end
local lines = {}
for line in io.lines(path) do
local words = {}
for word in line:gmatch("%w+") do
table.insert(words, word)
end
table.insert(lines, words)
end
file:close()
return lines;
end

There's a I/O library available, but if it's available depends on your scripting host (assuming you've embedded lua somewhere). It's available, if you're using the command line version. The complete I/O model is most likely what you're looking for.

Related

Lua: Yield error: attempt to index a nil value (local 'f')

I'm completely unfamiliar with Lua and I need to work with some Lua code.
I have the following method where I pass in a file and I want to read the contents of that file as a string.
function readAll(file)
local io = require("io")
local f = io.open(file, "rb")
local content = f:read("*all")
f:close()
return content
end
For that, I'm getting:
Lua: Yield error: [string "myFile.lua"]:101: attempt to index a nil value (local 'f')
The error appears on this row:
local content = f:read("*all")
Any idea what could be causing this?
The error means that io.open failed. To see why, try
local f = assert(io.open(file, "rb"))
or
local f,e = io.open(file, "rb")
if f==nil then print(e) return nil end

How to set up output to certain specifications

I figured out the main concept of my code which reads in a file and sets it to a key then reads in another file and displays the info based on that file. How do I add line 1, line 2. line 3 and so on in front of the output? As well as add ------------ above and below each new line.
-- see if the file exists
function file_exists(file)
local f = io.open("data.txt", "rb")
if f then f:close() end
return f ~= nil
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function lines_from(file)
if not file_exists(file) then return {} end
lines = {}
for line in io.lines("data.txt") do
first_word = string.match(line, "%a+") -- word
lines[first_word] = line
lines[#lines + 1] = lin
end
return lines
end
local lines = lines_from(file)
function key_file(file)
if not file_exists(file) then return {} end
keys = {}
for line in io.lines("keys.txt") do
key = string.match(line, "%a+")
table.insert(keys, key)
end
return keys
end
local lines = lines_from("data.txt")
local keys = key_file("keys.txt")
for _, key in ipairs(keys) do
print(lines[key])
end
I'll answer this in a more general way as your code is not working atm.
You can simply add print commands in the for loop that prints the lines. Or you alter the texts by in some way. See Lua reference documentation for string manipulation and concat operator ..
local numLine = 0
for _, key in pairs(keys) do
numLine = numLine + 1
print("Line " .. numLine .. ": " .. lines[key])
print("----------")
end

Display table information based on a file read in

So I was able to put data from a file into a table and set the first word of each line a key. How do I display whats in the table in an order based on reading in another file with just the keys?
-- see if the file exists
function file_exists(file)
local f = io.open("data.txt", "rb")
if f then f:close() end
return f ~= nil
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function lines_from(file)
if not file_exists(file) then return {} end
lines = {}
for line in io.lines("data.txt") do
first_word = string.gmatch(line, "%a+") -- word
lines[first_word] = line
end
return lines
end
local lines = lines_from(file)
end
You have some mistakes in your code:
-- see if the file exists
function file_exists(file)
local f = io.open(file, "rb") -- <-- changed "data.txt" to file
if f then f:close() end
return f ~= nil
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function lines_from(file)
if not file_exists(file) then return {} end
lines = {}
for line in io.lines(file) do -- <-- changed "data.txt" to file
first_word = string.match(line, "%a+") -- <-- changed gmatch to match (IMPORTANT)
lines[first_word] = line
end
return lines
end
local lines = lines_from(file)
I removed the last end since it didn't match any block.
The change gmatch to match is critical, since gmatch returns an iterator, a function.
Regarding your question: read the key file, but save its entries in an array manner:
function key_file(file)
if not file_exists(file) then return {} end
keys = {}
for line in io.lines(file) do
key = string.match(line, "%a+")
table.insert(keys, key)
end
return keys
end
In another place you iterate over the key array, using the keys for the lines table:
local lines = lines_from("data.txt")
local keys = key_file("keys.txt")
for i, key in ipairs(keys) do
print(string.format("%d: %s", i, lines[key]))
end

Is it possible to perform a hexdump in Lua code

I'm used to using C but I'm new to Lua. Is there a way to create a Lua program that can read example.exe and give me the program's code in hexadecimal?
Until Lua 5.1, this sample program xd.lua was included in the distribution:
-- hex dump
-- usage: lua xd.lua < file
local offset=0
while true do
local s=io.read(16)
if s==nil then return end
io.write(string.format("%08X ",offset))
string.gsub(s,"(.)",
function (c) io.write(string.format("%02X ",string.byte(c))) end)
io.write(string.rep(" ",3*(16-string.len(s))))
io.write(" ",string.gsub(s,"%c","."),"\n")
offset=offset+16
end
Another possibility:
local filename = arg[1]
if filename == nil then
print [=[
Usage: dump <filename> [bytes_per_line(16)]]=]
return
end
local f = assert(io.open(filename, 'rb'))
local block = tonumber(arg[2]) or 16
while true do
local bytes = f:read(block)
if not bytes then return end
for b in bytes:gmatch('.') do
io.write(('%02X '):format(b:byte()))
end
io.write((' '):rep(block - bytes:len() + 1))
io.write(bytes:gsub('%c', '.'), '\n')
end

Scanning folders using lua

I'm trying to get the name of all the file saved in two folders, the name are saved as :
1.lua 2.lua 3.lua 4.lua and so on
the folders name are :
first folder : "/const/"
second folder: "/virt/"
what I'm trying to do is only get the number of the files and this works but not in the right order, when I get the 17 file for example I get the 17th delivered from the function before the 15 and this causes for me a problem here the code of the function that I'm using :
local virt_path = "/virt/"
local const_path = "/const"
local fs = require "lfs"
local const = {}
for num = 1, (numberoffile)do -- numberoffile is predfined and can't be change
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)
local vi, vo, _ = fs.dir(virt_path)
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)
end
return iter, {co=co, vo=vo}, num
end
As I said the function delive the need return values but not the right Arithmetic order.
any idea what I'm doing wrong here ?
I use my path[1] library.
1 We fill table with filenames
local t = {}
for f in path.each("./*.lua", "n") do
t[#t + 1] = tonumber((path.splitext(f)))
end
table.sort(t)
for _, i in ipairs(t) do
-- do work
end
2 We check if files exists
for i = 1, math.huge do
local p = "./" .. i .. ".lua"
if not path.exists(p) then break end
-- do work
end
[1] https://github.com/moteus/lua-path

Resources