Rather than reading the file from the front, would it be possible to read it backwards? So that the output is from the back of the file to the front of the file.
EDIT: Last line displayed first, not fully backwards.
It's possible, but cumbersome. Lua API provides seek function to set and get position in a file that read/write operations apply to.
So, you can use "seek" to read the file in small chunks from the end (for example, seek to filesize-1024
position, read 1024
bytes, find all end-of-lines, print the complete lines and store the leftover) and continue doing that going backward to the beginning of the file. The main advantage is that you shouldn't spend much more memory than the buffer you are reading (where as if you are reading from the beginning, but want to print in the reverse order, you'd need to have the entire file in memory), but it's likely to be slow.
This solution is based on the idea of @PaulKulchenko.
Yes, it's cumbersome :-)
Define function io.linesbackward(filename)
in the io
library:
function io.linesbackward(filename)
local file = assert(io.open(filename))
local chunk_size = 4*1024
local iterator = function() return "" end
local tail = ""
local chunk_index = math.ceil(file:seek"end" / chunk_size)
return
function()
while true do
local lineEOL, line = iterator()
if lineEOL ~= "" then
return line:reverse()
end
repeat
chunk_index = chunk_index - 1
if chunk_index < 0 then
file:close()
iterator = function()
error('No more lines in file "'..filename..'"', 3)
end
return
end
file:seek("set", chunk_index * chunk_size)
local chunk = file:read(chunk_size)
local pattern = "^(.-"..(chunk_index > 0 and "\n" or "")..")(.*)"
local new_tail, lines = chunk:match(pattern)
iterator = lines and (lines..tail):reverse():gmatch"(\n?\r?([^\n]*))"
tail = new_tail or chunk..tail
until iterator
end
end
end
Usage:
local filename = "your_file.txt"
print("--- backward: ---------------------------")
for line in io.linesbackward(filename) do
print(line)
end
print("--- forward: ----------------------------")
for line in io.lines(filename) do
print(line)
end
print("-----------------------------------------")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With