如何有效地读取大文本文件中的行数

时间:2017-04-23 23:19:27

标签: lua

我有一个大约750,000行的大文本文件,每隔几秒就会不断更新,我希望能够实时监控行数。我能够做到这一点,但响应时间非常繁重。

function GetFileSize( filename )
  local fp = io.open( filename )
  if fp == nil then
    return nil
  end
  file = {}
  for line in fp:lines() do
    if (file[line] ~= line) then
      table.insert(file, line)
    end
  end
  d(table.size(file))
  local filesize = fp:seek( "end" )
  fp:close()
  return filesize
end

我正在尝试获取两个东西,大小(字节)和行数。

然而,一遍又一遍地填充750,000行,从上到下不断地读取文件会导致相当多的处理时间。

有没有办法以字节为单位获取文件大小,还可以获得行数,而不会严重阻碍我的系统。

我猜我必须在函数外部创建一个永久表,在那里你读取文件并将行添加到表中。但是,我不知道如何阻止它每隔几秒就重复一次。

我应该放弃行计数并坚持使用字节返回,因为这根本不会减慢我的速度吗?或者是否有一种有效的方法来获得两者。

谢谢!

3 个答案:

答案 0 :(得分:1)

尝试一次读取整个文件并使用gsub计算行数。你必须测试这是否足够快。

 t = f:read("*a")
 _,n = t:gsub("\n","")

答案 1 :(得分:1)

我可以建议这个解决方案。这不需要读取所有大文件。

local function char_count(str, ch)
  local n, p = 0
  while true do
    p = string.find(str, ch, p, true)
    if not p then break end
    n, p = n + 1, p + 1
  end
  return n
end

local function file_info(name, chunk_size)
  chunk_size = chunk_size or 4096
  local f, err, no = io.open(name, 'rb')
  if not f then return nil, err, no end
  local lines, size = 0, 0
  while true do
    local chunk = f:read(chunk_size)
    if not chunk then break end
    lines = lines + char_count(chunk, '\n')
    size = size + #chunk
  end
  f:close()
  return size, lines
end

但是,如果您只需要监控一个文件并在其中计数行,则可能只使用任何文件监控解决方案。我使用一个based on LibUV

答案 2 :(得分:0)

要以字节为单位获取文件大小,请使用Lua Filesystem。对于您可能想要使用io.lines迭代器的行数。为了更好地执行后者,在{Lua编程«中描述了a trick

local file = arg[0] -- just use the source file for demo

-- Get the file size
local lfs = assert(require"lfs")
local attr = lfs.attributes(file)
print(attr.size)

-- Get number of lines
local count = 0
for line in io.lines(file) do
   count = count + 1
end
print(count)