2010-12-10 78 views
1

我想快速高效地列出包含在單個目錄中的大量文件(10,20,000左右)。 我已經閱讀了不少帖子,特別是在這裏解釋了Java的短暫實現,主要由於底層文件系統(可能Java 7對此有一些答案)。 這裏的一些帖子提出了諸如本地調用或管道等替代方案,並且我明白在正常情況下最好的選項是java調用 - String [] sList = file.list();這隻比file.listFiles()稍微好點; 此外,還有一個使用多線程(也是Executor服務)的建議。Java:從單個目錄中列出所有文件(10-20,000 +)

那麼,這裏的問題是我很少有如何編碼多線程方式的實用知識。所以我的邏輯必然是錯誤的。不過,我想是這樣的:

  1. 創建的對象
  2. 然此列表的環數線程的列表,稱爲。開始(),並立即。睡眠(500)
  3. 在線程類,過度騎着運行methos到包括.LIST()

這樣的事情,主叫類 -

String[] strList = null; 
for (int i = 0; i < 5; i++){ 
    ThreadLister tL = new ThreadLister(fit); 
    threadList.add(tL); 
} 
for (int j = 0; j < threadList.size(); j++) { 
    thread = threadList.get(j); 
    thread.start(); 
    thread.sleep(500); 
} 
strList = thread.fileList; 

和Thread類作爲 -

public String[] fileList; 
public ThreadLister(File f) { 
    this.f = f; 
} 
public void run() { 
    fileList = f.list(); 
} 

我可能會離開這裏與多線程,我想這一點。 我非常感謝我的多線程要求的解決方案。額外的好處是我會學習更多關於實用多線程。

查詢更新

那麼,顯然多線程是不是要幫我(以及我現在認識到它並不是一個真正的解決方案)。感謝您幫助我排除線程。
所以我試過了,
1. FileUtils.listFiles()來自apache commons--差別不大。
2.本地電話即, exec("cmd /c dir /B .\\Test") - 這裏執行速度很快,但是當我使用需要時間的while循環讀取Stream時。

實際上我需要的是文件名,取決於單個目錄中大約100k個文件中的某個過濾器。所以我使用像File.list(new FileNameFilter())
我相信FileNameFilter沒有任何好處,因爲它會嘗試首先匹配所有文件,然後發出輸出。
是的,據我所知,我需要一種不同的方法來存儲這些文件。我可以嘗試的一個選擇是將這些文件存儲在多個目錄中,但我還沒有嘗試過(我不知道這是否會有所幫助) - 正如鮑里斯之前提出的
還有什麼可以是一個更好的選擇,在Unix上的本地調用ls與文件名匹配有效地工作。我知道在Windows上它不工作,我的意思是,除非我們在同一個目錄正在尋找

親切的問候

+1

我也懷疑使用多線程將會有所幫助,因爲沒有辦法告訴「list()」方法從哪裏開始列出文件,所以你最終會重新創建列表多次。 – camickr 2010-12-10 16:25:53

+0

看來你必須退一步,重新思考將多個文件存儲在一個目錄中的實現。例如,看看蘋果如何用他們的iPod解決了這個問題。有大約50個用於保存文件的文件夾。 – 2010-12-10 16:29:14

+0

@camickr - 是的,當我試圖運行此程序時,它確實多次顯示列表長度。 – 2010-12-10 16:46:29

回答

0

最終,我做了什麼。
1.作爲一個quickfix,爲了解決這個問題,我使用本地調用將所有文件名寫入臨時文本文件,然後使用BufferedReader讀取每一行。
2.編寫一個實用程序將非活動文件(大部分)歸檔到其他歸檔位置,從而減少活動目錄中的文件總數。所以正常的list()調用返回得更快。 3.但是,作爲一個長期解決方案,我將修改所有這些文件的存儲方式,並創建一種目錄層次結構,其中每個目錄將保留相對較少的文件,因此list()可以工作非常快。

有一件事出現在我的腦海裏,當我第一次運行需要很長時間但後來的請求非常快時,我注意到當測試是這個列表()時。讓我相信JVM不情願地檢索堆在一起的列表。我嘗試了一些東西,例如將文件添加到目錄或更改File變量名稱,但仍然是即時響應。所以我相信這個數組會坐在堆上直到gc和Java智能地響應相同的請求。由於這個原因,我想,如果我可以編寫一個小程序來每天獲取一次這個列表並保留一個靜態引用,那麼這個數組將不會被gc化,並且每一個檢索這個列表的請求都會很快。 <*Again, some comments/suggestion appreciated.*>
有沒有辦法配置Tomcat,其中GC可能gc所有其他未引用的對象,但不適用於某些指定的對象?有人在Linux中告訴我這樣的事情顯然是在OS級別實現的,但我不知道它是否正確。

5

多線程是列出多個目錄非常有用。然而,你不能將一個單獨的調用分割到一個單獨的目錄中,並且如果你可以按照任意順序返回文件,我懷疑它會更快。

學習多線程的第一件事就是,並不是所有的解決方案都會使用多線程更快或更簡單。

2

上午作爲一個完全不同的建議。你有沒有嘗試使用Apache Commons File util?

http://commons.apache.org/io/api-release/index.html檢出FileUtils.listFiles()方法。

它會列出目錄中的所有文件。也許它足夠快並且足夠滿足您的需求。也許你真的不需要重新發明輪子,解決方案已經在那裏了?

+0

@ Apache - 感謝這個建議,我也會試着實現這個。 – 2010-12-10 16:50:48

0

您正在使用哪種文件系統?每個文件系統對於目錄可以具有的文件/文件夾的數量(包括目錄深度)有其自身的限制。所以不知道你如何創建,如果通過某些程序創建,你可以讀取所有文件。

如上面建議的FileNameFilter是一個過帳文件名過濾器,所以我不確定它是否會有幫助(儘管您可能會創建較小的文件列表),因爲每個listFiles()方法都會得到完整列表。

例如: 1)假設線程1捕獲開始以「T * 」文件名列表,listFiles()調用會檢索所有數以千計的文件名,然後過濾按FileNameFilter標準 2)螺紋2,如果捕獲以「S *」開頭的文件名列表將重複從1開始的所有步驟。

因此,您多次閱讀目錄列表,將越來越多地加載到Heap/JVM本地調用/文件系統上。

如果可能,最好的建議是重新組織目錄結構。

+0

你從第二個電話看到更好的迴應的原因可能是由於多種原因: 1)操作系統可能本機緩存目錄結果(將其帶到內存)並保留一段時間 - 一個好的測試將是在第一次運行一小時左右後再次列出文件。 2)JVM是緩存的,因爲所有的修改都是通過你的java程序執行的,它正在修改緩存中的文件列表(我嚴重懷疑這種方法,因爲JVM不能夠讀取外部修改 - 陳舊列表) – Rajendra 2011-03-10 15:35:09

+0

仍然不明白你爲什麼寫了一個本地調用來將目錄列表寫入文件。您可以使用Runtime.exec命令來處理文件並將其寫入列表。 list()/ listFiles()命令本身使用本地調用來檢索文件系統。如果列表太大,您可能會遇到內存問題。 – Rajendra 2011-03-10 15:36:12

相關問題