Lua能否实现文件“反向”读取?

4

是否可以反向读取文件,使输出从文件的末尾到文件的开头?

编辑:最后一行先显示,但不完全反向。


完全倒过来,所以你得到'sdrawkcab'?还是只是将最后一行显示在第一行? - Marc B
需要满足O(n)时间复杂度吗? - Eli Sadoff
@MarcB 最后一行先显示 - fishy
3个回答

4

这是可能的,但很麻烦。Lua API提供了seek函数,用于设置和获取读写操作应用于的文件位置。

所以,你可以使用“seek”从文件末尾读取小块文件(例如,将位置定位到filesize-1024,读取1024字节,找到所有换行符,打印完整行并存储剩余部分),并继续向后移动到文件开头。主要优点是你不需要比正在读取的缓冲区更多的内存(如果你从开头读取,但想按相反顺序打印,则需要在内存中拥有整个文件),但速度可能会较慢。


3

这个解决方案基于@PaulKulchenko的想法。
是的,它很繁琐:-)

io库中定义函数io.linesbackward(filename)

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

使用方法:

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

1

不使用标准库。但是您可以按行从头到尾阅读它,将其存储在表中,然后从最后一行开始“使用”它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接