2009-02-04 90 views
8

我需要創建一個Java程序,該程序將創建線程來搜索特定文件夾(源文件夾)中的文件,並立即選擇該文件進行工作(將其轉換爲csv文件格式),一旦發現該文件在源文件夾。我現在面臨的問題是源文件夾大的文件(FTP工具用於將文件從服務器複製到源文件夾),線程在完全複製到源文件夾並拋出異常之前正在拾取該文件。直到文件完全複製到源文件夾中,我該如何停止線程?只有在將文件完全複製到源文件夾中後,才能選擇要處理的文件。如何處理不完整的文件?獲取異常

+0

它很高興知道,什麼例外? – 2009-02-04 06:34:09

回答

1

假設你已經在FTP過程中沒有控制...

讓它成爲這個樣子。當你得到異常,然後嘗試再次處理它。重複它直到文件得到處理。在例外的情況下保留少量屬性以便稍後檢查它,比如;名稱,最後修改的大小。

在決定稍後處理它之前檢查確切的異常,該異常可能會出於某種其他原因。

2

如果你對此做了FTP過程中的一些控制你可能有它建立在源目錄中的「標誌文件」立即FTP後的大文件完成。

那麼你的Java線程必須檢查這個標誌文件的存在,如果它存在,那麼有一個文件準備源目錄進行處理。在處理大文件之前,線程應該刪除標誌文件。

標誌文件可以是任何東西(甚至是空文件)。

3

你可以嘗試不同的東西:

  • 反覆檢查的最後修改日期和文件的大小,直到它不爲一個特定的時間量不再改變,然後對其進行處理。 (正如qbeuek指出,這是既不安全也不確定。)
  • 與符合特定條件(例如* .dat文件)名稱只能處理文件。更改FTP上傳/下載過程以上傳/下載具有不同名稱的文件(例如* .dat.temp),並在文件完成後重命名文件。
  • 將文件下載到其他位置,並在完成後將它們移動到您的處理目錄。正如醋所說,如果它第一次不起作用,請稍後再試。 :)
+0

我不知道爲什麼我們有時會降低價格。人們開始在任何地方拍攝。 100的聲譽太低而無法擊倒某人。它必須更高,可能是1000或2000. – 2009-02-04 07:04:46

+0

嗯,有時候我會投票贊成平衡降低票數,給予他們否則不會收到的票數+8分,所以這是一些事情。在這種情況下,無論如何我都會投你的回答,很難。 – itsadok 2009-02-04 07:12:01

4

最安全的方法是將文件下載到其他位置,然後將其移動到目標文件夾。

通過氣罐提到的另一個變化是下載後的文件名更改爲其他擴展,只尋找與該擴展名的文件。

4

我只讀取未處於寫入模式的文件。這是最安全的,因爲這意味着此文件中沒有其他進程正在寫入。您可以使用File類的canWrite方法檢查文件是否不處於寫入模式。

該解決方案適用於我,因爲我也有完全相同的場景。

0

如果您的操作系統是Linux,並且您的內核> 2.6.13,則可以使用名爲inotify的文件系統事件通知API。 這裏有一個Java實現:https://bitbucket.org/nbargnesi/inotify-java

下面是一個示例代碼(深受網站的啓發)。

 try { 
     Inotify i = new Inotify(); 
     InotifyEventListener e = new InotifyEventListener() { 

      @Override 
      public void filesystemEventOccurred(InotifyEvent e) { 
       System.out.println("inotify event occurred!"); 
      } 

      @Override 
      public void queueFull(EventQueueFull e) { 
       System.out.println("inotify event queue: " + e.getSource() + 
         " is full!"); 
      } 

     }; 
     i.addInotifyEventListener(e); 
     i.addWatch(System.getProperty("user.home"), Constants.IN_CLOSE_WRITE); 
    } catch (UnsatisfiedLinkError e) { 
     System.err.println("unsatisfied link error"); 
    } catch (UserLimitException e) { 
     System.err.println("user limit exception"); 
    } catch (SystemLimitException e) { 
     System.err.println("system limit exception"); 
    } catch (InsufficientKernelMemoryException e) { 
     System.err.println("insufficient kernel memory exception"); 
    } 
0

這是在Grails中,我使用FileUtils來自Apache commons fame的庫。函數sizeof以字節爲單位返回大小。

def fileModified = sourceFile.lastModified() 
    def fileSize = FileUtils.sizeOf(sourceFile) 

    Thread.sleep(3000) //sleep to calculate size difference if the file is currently getting copied 

    if((fileSize != FileUtils.sizeOf(sourceFile)) && (fileModified != sourceFile.lastModified())) //the file is still getting copied to return 
    { 
     if(log.infoEnabled) 
      log.info("File is getting copied!") 
     return 
    } 

    Thread.sleep(1000) //breather for picking up file just copied. 

請注意,這也取決於你所使用傳輸的文件有什麼實用程序或操作系統。 最安全的選擇是複製已複製或已複製到不同文件或目錄的文件。複製過程是穩健的,它可以確保文件在複製過程後出現。我正在使用的是來自commons API。

FileUtils.copyFileToDirectory(文件F,目錄d)

如果您要複製一個巨大的文件,該文件是在得到複製提防的過程,這需要時間,你可能會喜歡的並行線程或最開始這個有一個專門用於傳輸過程的獨立應用程序。