看板 java 關於我們 聯絡資訊
Hi all, 想請問大家都怎麼偵測大檔案copy完成了呢? 使用情境是: user丟大型檔案到指定資料夾 > 抓到這個事件 > 做其他事情 問題點: 現在卡在"抓到這個事件"有點不太好處理, 想請各位版友分享類似經驗 已嘗試方法: 1) 透過 nio 的 WatchService 這個方法基本上就是google的第一種解法, 透過 nio 的 WatchService, 註冊 ENTRY_MODIFY/ENTRY_CREATE 可偵測到檔案有變動or新增 但無法無法知道何時copy完成 2) 在 nio 的 WatchService 判斷 天真如我, 在每次 ENTRY_MODIFY 事件發生時, 將 Path 轉為 File, 判斷檔案是否可用 File f = path.toFile(); if(f.canWrite()){ ... } 會用 canWrite() 判斷是因為有爬到說在copy時檔案不能編輯 這個方法我一直覺得可能是我哪邊寫錯了, 因為我覺得應該要可以 Orz 3) 定時爬一次資料夾 這是土炮, 也是唯一成功的一種... for(;;){ ...; Thread.sleep(5000); } 不想用這種方法的原因是, 類似的回答在 stackoverflow 被推到 -1x 也有人點出效能的問題 以上是我嘗試過的幾種方式, 不知道有沒有其他我沒想過的做法可以提供參考 跪謝 -- 不菸不酒,沒有朋友 有菸有酒,癌症好友 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.224.100.95 ※ 文章網址: https://www.ptt.cc/bbs/java/M.1470329900.A.A79.html
ripple0129: public void observe(){ copyingFile(); notifyDone() 08/05 01:56
ripple0129: ;} 08/05 01:56
謝謝 可以詳述一下這是怎麼做的嗎@@? 只有兩個function name 我參悟不出來 Orz ※ 編輯: love112302 (61.224.100.95), 08/05/2016 08:45:11
ripple0129: 簡單來說你寫copy的那個method最後一行加個通知完成 08/05 09:11
ripple0129: 的method 08/05 09:11
ripple0129: 不過不太確定你的寫法適合嗎,我是都用古老的copy寫法 08/05 09:13
ripple0129: 。 08/05 09:13
Hi, 謝謝您的意見, 但是 copy檔案這個部分不是我做的 是使用者自行丟檔案到特定資料夾, 所以好像沒辦法這樣做 @@?
dennisxkimo: 那是偵測檔案異動 不適合你的需求 08/05 11:50
dennisxkimo: 如果丟檔的行為 也是靠你的程式處理 那就很簡單單純 08/05 11:51
dennisxkimo: 而且至少還能掌握大檔丟完後的完整性 08/05 11:56
dennisxkimo: 寫批次也能做到 複製完 %errorlevel%跟起始時間出log 08/05 12:03
謝謝 想請問批次是指 batch? 不好意思這塊不太熟, 我原本也是想用 batch 來監看資料夾, 如果copy完成, 執行特定的 jar 檔案, 但因為command line 指令不熟放棄 T__T ※ 編輯: love112302 (114.46.155.75), 08/05/2016 15:27:26
cowbaying: WatchService 通常會配一個雜湊檔... 08/05 16:17
cowbaying: 重點是WatchService是事件驅動 比THREAD省資源 08/05 16:19
cowbaying: 不過事件驅動的本質還是THREAD... 08/05 16:21
cowbaying: 其實你如果執行緒夠熟 也是能寫的 08/05 16:21
cowbaying: 看你用sleep硬幹就知道你應該不太熟 08/05 16:22
cowbaying: 建議你還是把WatchService弄熟比較快 08/05 16:22
cowbaying: 不好意思 沒看清楚 你第一個方法應該是去檢查兩邊 08/05 16:24
cowbaying: 檔案的MD5是不是一致這樣就好了 08/05 16:25
cowbaying: 檔案能否寫入跟OS實作FS的方式有關 所以這個方法不好 08/05 16:26
謝謝, 我對Thread 真的不熟...Orz 想請問檢查MD5 的部分是指 來源 跟 複製檔案的 md5 嗎? 比方說: c:\source\from.big.file.txt 跟 d:\des\from.big.file.txt 這兩個檔案的 md5 嗎? 還是 ? 謝謝您的回覆
bitlife: 其實正本清源是要有protocol,以現在你描述的現況,你根本 08/05 17:09
bitlife: 無法檢查何謂檔案copy好了. 必須有個明確的協定,例如使用 08/05 17:09
bitlife: 者可先在其他暫存目錄建立好檔案,然後用move的方式,這樣 08/05 17:10
bitlife: 目標目錄下的檔案一出現就是完整的. 又或者使用者copy完 08/05 17:10
bitlife: 檔案,就touch一個特定格式檔名,這樣看到這個特定檔也可確 08/05 17:11
bitlife: 定copy完成,這個標記用檔案處理完由你的程式刪除即可 08/05 17:12
bitlife: 補充一下我所謂你無法確定檔案是否copy完了的意思是,除非 08/05 17:14
bitlife: 你事先知道(或可計算)檔案完整長度,否則你無法確定檔案目 08/05 17:15
bitlife: 前是已copy完成,還是對方程式只是剛好停頓檔案短時間沒再 08/05 17:15
bitlife: 有內容變動 08/05 17:16
※ 編輯: love112302 (114.46.155.75), 08/05/2016 18:02:34 謝謝您~ 但是我沒有辦法要求使用者的動作 他們只想要把檔案拉進去這個資料夾就沒事了 Orz 我是有看到有人使用 File.length() 的方式, 然後幾秒沒有更新, 就判斷 File is ready 但是我在 WatchService 裡面用 Path.toFile().length() 每次都是 0 T___T ※ 編輯: love112302 (114.46.155.75), 08/05/2016 18:05:29
haha02: 你可以看一下File的API https://goo.gl/ChHnPB 08/05 19:18
haha02: 他有說有些情況會回傳0 08/05 19:19
cowbaying: 感覺像是網芳或者FTP這種單向的 08/05 19:49
cowbaying: WatchService 一開始會檢測到CREATE事件 檔案傳完會 08/05 19:50
cowbaying: 檢測到MODIFY事件 其實這樣就蠻簡單了 08/05 19:51
cowbaying: 除非你規定他們傳檔時要有加個驗證檔案 MD5或SHA的 08/05 19:53
cowbaying: 這樣你後端就能檢查檔案完整性 08/05 19:53
謝謝, 想請問 即使是抓到 create 跟 modify 事件, 要如何判斷 因為我在最後一次觸發 Modify 的時候 去檢查檔案 File.canWrite() or File.length() 都沒有用 :(
ripple0129: 我覺得3的方式可行啊,1個thread大多數的時間在睡覺 08/05 23:08
ripple0129: 能吃什麼資源,不過多學WatchService也是好的。 08/05 23:08
但是就覺得是個技術債, 有一種遲早要還的感覺 XD 可能是因為死線還沒到 所以還不願意放行XD
jej: 如果是別人做copy 不是就偵測copy的pie?? 08/05 23:12
謝謝 我來研究一下這是什麼意思XD
qrtt1: jej 提供的思路挺棒的 08/06 19:00
※ 編輯: love112302 (61.224.156.163), 08/07/2016 22:46:43
cowbaying: 我是根據其API來看的 08/07 23:31
cowbaying: MODIFY的時機就是檔案被改寫 08/07 23:31
cowbaying: 那檔案什麼時候被改寫 FILE IO結束的時侯 08/07 23:31
cowbaying: FILE IO什麼時候結束? 資料中斷或者寫完的時候 08/07 23:32
cowbaying: 所以我才會說如果是我所說的那種單向上傳 08/07 23:32
cowbaying: 你只能透過SHA或MD5來驗證檔案完整性 08/07 23:32
cowbaying: WatchService只是監控IO的情況而已 08/07 23:33
※ 編輯: love112302 (61.224.156.163), 08/07/2016 23:36:17
tacovirus: 歡迎來看原始碼,稍候回文 08/25 00:52
Chikei: 嘗試去lock檔案,其他程式copy當中你應該是不能lock的 08/27 22:40
Chikei: 能lock就是copy完成了 08/27 22:40