为什么在lua中读取文本文件只返回最后一个块?

时间:2015-12-14 00:47:46

标签: lua

我正在尝试读取一个大文件并返回一个包含字数的表。 我找到了一个在lua.org上有效读取大文件的例子,并提出了我的小脚本的最终版本。

function cnt_word(stream)
  local BUFSIZE = 2^13 -- 8KB
  local sin = io.input(stream) -- open input file
  local wc = {}
  local text = ""
  while true do
    local data, line = sin:read(BUFSIZE, '*l')
    if not data then break end
    if line then data = data .. line .. '\n' end
    text = data
  end
  -- creating a table with word counts
  for m in text:gmatch("%w+") do
    if not wc[m] then wc[m] = 0 end
    wc[m] = wc[m] + 1
  end
  return wc
end

input, word = arg[1], arg[2]
if not input then print("Error! Provide a valid filename") os.exit() end
if not word then print("Error! Provide a valid query term") os.exit() end
cnts = cnt_word(input)
cnt = cnts[word]
if not cnt then
  print(string.format("'%s' not found in '%s'", word, input))
  os.exit()
  end
print(string.format("'%s' cnt: %s", word, cnt))

这个脚本的问题是它只返回文件的最后~70行,我无法弄清楚原因。行连接if line then data = data .. line .. '\n' end执行〜3k次,这足以收集data变量中的整个数据。然而,当我检查循环内data的长度时,它不会增长但会在8k左右波动,而且当我检查text的长度时,由于某种原因,它是〜3k。我不明白Lua对数据做了什么以及它为什么这样做。有人可以帮我搞清楚吗?

2 个答案:

答案 0 :(得分:1)

考虑一下你的代码在做什么。

local data, line = sin:read(BUFSIZE, '*l')

您读取X字节数据,然后读取下一个结束行。

if not data then break end

如果没有读取数据,请返回。

if line then data = data .. line .. '\n' end

如果line包含数据,则将其连接到总数中。

text = data

那么......你认为那是什么意思?我知道做了什么。它不会连接数据块与已加载的数据。 已经替换该变量中的任何内容。

这意味着text存储的最后一件事......是您加载的最后一个数据块。

关于效率的一句话。

您在Lua.org上阅读的关于有效加载大文件的内容是正确的。但是代码是假设你要加载一个块,然后进程那个块,然后加载另一个。

你正在做的是按块加载文件块,然后连接它们(好的,你实际上正在那样做,但这就是你想要的;)),然后处理整个文件。

效率不高。如果你想加载整个文件,那么当它处于mempry时处理整个文件,这就是read("*a")的用途。

答案 1 :(得分:0)

你应该在text = data之后移动在while循环中调用单词计数的代码。

代码中总体上发生的是以BUFSIZE的块大小读取文件。然后应该处理该块,然后用下一个块替换块。 因为所有的工作都是在完成所有读取后完成的,所以单词计数功能只处理它读取的最后一个块,而不是所有的块。