lua自定义目录迭代器

时间:2017-03-02 10:11:07

标签: list lua iterator directory lua-table

我正在开发一个不支持lua文件系统库的系统。所以我必须创建自己的目录迭代器,它给出了具有特定格式的完整路径的文件列表。

系统有一个我们可以为目录路径设置的API,另一个API用于以lua表格式获取该目录中的文件列表。

API:FileSetDir()将目录设置为获取文件列表。 API:FileList()给出了我们使用API​​设置的目录中的文件列表表:FileSetDir()。

例如,请考虑以下目录结构。

Movies/3d Movies/Avatar/Avatar.mp4
Movies/3d Movies/Avengers/Avengers.mkv
Movies/3d Movies/ironman.mp4
Movies/Horor/Ring/Ring.avi
Movies/Horor/A Nightmare On Elm Street/A Nightmare On Elm Street.iso
Movies/Barfi.mkv

我的代码..

RootDirList1 = {}
RootDirList = {}
finalpath={}


function SetDIR(v)
    if v=="" then
        RootDir = '/mnt/media/net/192.168.1.40_usbshare1/Movies/'
    else
        RootDir = '/mnt/media/net/192.168.1.40_usbshare1/Movies/'..v
    end
    API:FileSetDir (RootDir)
    RootDirList1 = API:FileList ()
    CheckDirectory()
end

function CheckDirectory()
    for i,v in pairs(RootDirList1) do
        local RootDir = '/mnt/media/net/192.168.1.40_usbshare1/Movies/'..v
        API:FileSetDir (RootDir)
        local RootDirList = API:FileList ()
        if RootDirList == nil then
            print(v)
            print("Not Directory")
            if string.find(v,"%.mkv$") or string.find(v,"%.mp4$") then 
                finalpath[#finalpath+1] =RootDir.."/"..t
           print(RootDir.."/"..t)

            end
        else    
            CheckDirectory(v)
       end
    end
end 

SetDIR("")

代码在" Stack Overflow"。

中给出了错误

SetDIR使用API​​设置目录:FileSetDir(RootDir)并获取RootDirList1表中的文件列表。然后我调用函数CheckDirectory()这里我在RootDirList1表上运行for循环,如果表项是文件,它将存储在finalpath表中。如果表条目是目录,则它调用SetDIR以获取该目录中的文件列表。

我知道我的方法是错误的,使这项工作任何好主意都会受到高度赞赏。

2 个答案:

答案 0 :(得分:2)

堆栈溢出(heh)意味着堆栈溢出 - 它已满。堆栈基本上是一个内存区域,就像IRL堆栈一样:你可以在它上面放置一些东西(推送)或者把它取回(pop)。

Lua有多个筹码。这里重要的是调用堆栈:当你调用一个函数时,你将一个值推送到它(返回后恢复的位置)。它是有限的,所以你不能消耗无限的记忆。

因此,基本上,您的代码会导致无限递归。它会调用自身并且不会进展,因此它只会填满内存而不会执行任何操作。

话虽如此,你的错误就在这一行:

local RootDir = '/mnt/media/net/192.168.1.40_usbshare1/Movies/'..v

你试图递归列出 ,对吧?这根本不是递归的。该行假设该文件位于根文件夹“Movies”中,该文件夹生成无限递归,因为它一遍又一遍地反复检查同一文件夹。相反,您应该附加到当前的RootDir

我认为CheckDirectory(v)也参与其中。那是什么意思? CheckDirectory没有参数! (感谢Egor指出这一点)

下面,我重构了您的代码,完全改变了操作以提高效率,并修复了身份问题。

function CheckDirectory(dir)
    local result = {}

    -- set directory to dir, then list it
    API:FileSetDir(dir)
    local list = API:FileList()

    for i, v in pairs(list) do
        API:FileSetDir(dir .. v .. "/") -- fixed!

        local clist = API:FileList()

        -- don't compare to nil. Just use 'not clist'.
        -- And besides, we have an else, so I inverted everything
        -- and collapsed the else .. if into elseif.
        if clist then
            for i, v in ipairs(CheckDirectory(dir .. v .. "/")) do
                table.insert(result, v)
            end
        elseif string.find(v, "%.mkv$") or string.find(v, "%.mp4$") then
            table.insert(result, dir .. v)
            print(dir .. v) -- remove this line if you don't want to print
        end
    end

    return result
end 

local files = CheckDirectory('/mnt/media/net/192.168.1.40_usbshare1/Movies/')

答案 1 :(得分:0)

我使用lfs模拟了您的API并编写了有效的代码:

-- My block. Do not use in your project. ------
local lfs = require "lfs"
local API = { }

function API:FileSetDir(path)
        return lfs.chdir (path)
end
function API:FileList()
    local path= lfs.currentdir ()
    local t = {}
    for entry in lfs.dir(path) do
        t[#t+1] = entry
    end
    return t
end
--- End of my block ----------------------------------------------------
local finalpath={}
local RootDir = 'd:/temp'


function CheckDirectory(entry)
        local CurDir = entry
        local IsDir = API:FileSetDir(CurDir)  -- return nil when error
        local DirList = API:FileList()
        print(CurDir)
        if not  IsDir  then
                    print(CurDir .." - Not Directory")
        else    
                     for _,v in pairs(DirList) do
                                local tmp  = CurDir.."/".. v
                                if true or string.find(v,"%.mkv$") or string.find(v,"%.mp4$") then  -- true always  for me
                                        finalpath[#finalpath+1] = tmp
                                        print(' >> '..tmp)
                                end
                                if not (v=='.' or v=='..') then                             
                                  CheckDirectory(tmp)
                                end
                    end
        end     
end 

CheckDirectory(RootDir)