2017-03-02 92 views
1

我正在一個不支持lua文件系統庫的系統上工作。所以我必須做我自己的目錄迭代器,給出我具有特定格式完整路徑的文件列表。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("") 

的代碼給我的錯誤與 「堆棧溢出」。

SetDIR使用API​​設置目錄:FileSetDir(RootDir)並獲取RootDirList1表中的文件列表。那麼我調用函數CheckDirectory()在這裏,如果表項是文件,它將存儲在最終路徑表中,我在RootDirList1表上運行for循環。如果表項是目錄,則它調用SetDIR以獲取該目錄中的文件列表。

我知道我的做法是錯誤的,使這項工作任何明智的想法將不勝感激。

+1

檢查過剩 「或」 串 「如果string.find(V」 %$ MKV 「)或string.find(V」 %$ MP4 「)或則」 –

+0

哦,這是一個錯字原來的代碼沒有這個。 –

+2

函數CheckDirectory() - 不帶參數的無限次呼叫 –

回答

2

堆棧溢出(嘿嘿)表示,好了,堆得滿滿當當 - 這是滿的。一個堆棧基本上是一個內存區域,實際上就像是一個IRL堆棧:您可以在其上放置一些東西(push)或將其放回(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/') 
+0

哇作品安靜好。沒有CPU打嗝。唯一的問題是所有路徑末尾都有相同的電影名稱。 「根據南極洲 - 完整紀錄片HD.mp4」 –

+0

/mnt/media/net/192.168.1.40_usbshare2/Movies/3D電影/瑜珈熊3D /在南極洲下 - 完整紀錄片HD.mp4 /mnt/media/net/192.168.1.40_usbshare2 /電影/ 3D電影/ TRON遺產(2010)[3D] [HSBS] /在南極洲 - 完整紀錄片HD.mp4 等等...... –

+0

結束了我忘了把't'改成'v'。固定。 (你可能有一個全局't'被定義爲該字符串) – jv110

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) 
+0

我正在使用的系統不支持Ifs庫。 –

+1

@ Prakash.DTI但是你有一個我沒有的API。替換你的功能。 –

+0

你代表什麼? –