2012-01-18 61 views
1

我试图寻找相当大的文件一定的字符串,返回其偏移一个字符串的偏移量。我是新来的Lua和我目前的做法是这样的:回用LUA

linenumber = 0 
for line in io.lines(filepath) do 
result=string.find(line,"ABC",1) 
linenumber = linenumber+1 

if result ~= nil then 
offset=linenumber*4096+result 
io.close 
end 
end 

我意识到,这种方式非常原始,肯定慢。我怎么能更有效地做到这一点?

在此先感谢。

回答

2

如果文件不是太大,你可以备用内存,只需要在整个文件中使用,只需使用string.find即可。如果不是,您可以按块搜索文件。

你的做法是不是所有的坏。我建议加载文件在重叠块中。重叠避免了模式只是块之间的分裂,会被忽视,如:

".... ...A BC.. ...." 

我的实现是这样的:

size=4096 -- note, size should be bigger than the length of pat to work. 
pat="ABC" 
overlap=#pat 
fh=io.open(filepath,'rb') -- On windows, do NOT forget the b 
block=fh:read(size+overlap) 
n=0 
while block do 
    block_offset=block:find(pat) 
    if block_offset then 
     print(block_offset) 
     offset=block_offset+size*n 
     break 
    end 
    fh:seek('cur',-overlap) 
    cur=fh:seek'cur' 
    block=fh:read(size+overlap) 
    n=n+1 
end 

if offset then 
    print('found pattern at', offset, 'after reading',n,'blocks') 
else 
    print('did not find pattern') 
end 

如果你的文件确实有行,你也可以使用的伎俩解释here。在Lua中的编程中的This section解释了读取文件的一些性能考虑事项。

+0

非常感谢您的示例!它像一个魅力。我按照第21.1节的方式工作。在发布我的问题之前,lua代码书的内容,但我错过了21.2.1,所以感谢提示! 我还不熟悉“#” - 符号的概念。显然你使用它来创建重叠,但是在lua代码簿中是否有一个部分详细解释了它的用法以及其重叠大小等功能? – Zerobinary99 2012-01-18 11:55:18

+0

感谢您用实际的代码丰富我的答案。 – lhf 2012-01-18 14:52:51

+0

'#'操作符只是返回字符串的长度,作为序列的表(键是1到n,没有孔)或定义__len元方法的对象。请注意,字符串的长度是*字节数*,它不一定等于字符数(认为UTF-8等)。 – jpjacobs 2012-01-19 08:20:56

1

除非你的线都相同lenght(4096),我没有看到你的代码是如何工作的。

而不是使用io.lines的,读取的块与io.read(4096)。剩下的代码可以按原样使用,除了需要处理字符串不完全在块内的情况。如果文件由行组成,那么在Lua编程中提到的一个技巧是做io.read(4096,"*l"),读取以行边界结束的块。然后,你不必担心字符串不完全块内部,但你需要调整偏移计算包括块的长度,而不仅仅是4096

+0

感谢您的快速回复!我用进程监视器解析了io.lines阅读行为,结果表明该文件是以4096byte块读取的,所以我认为这是io.lines的标准值。你解决了我的问题。再次感谢! – Zerobinary99 2012-01-18 10:31:17