目前我正在處理在其中一個例程中處理來自源目錄的文件的項目。有一個Java進程正在查找指定的目錄,並嘗試讀取和處理存在的文件。文件很大並且由其他第三方進程更新。問題是如何檢查文件是否完整寫入?我正在嘗試使用file.length()
,但即使寫入過程尚未完成,它也會返回實際大小。我有一種感覺,解決方案應該取決於平臺。任何幫助,將不勝感激。檢查文件是否完全寫入
更新: 這個問題與重複實際沒有什麼不同,但它有一個工作代碼片段的答案,得到高度評價。
目前我正在處理在其中一個例程中處理來自源目錄的文件的項目。有一個Java進程正在查找指定的目錄,並嘗試讀取和處理存在的文件。文件很大並且由其他第三方進程更新。問題是如何檢查文件是否完整寫入?我正在嘗試使用file.length()
,但即使寫入過程尚未完成,它也會返回實際大小。我有一種感覺,解決方案應該取決於平臺。任何幫助,將不勝感激。檢查文件是否完全寫入
更新: 這個問題與重複實際沒有什麼不同,但它有一個工作代碼片段的答案,得到高度評價。
生產者進程在寫完文件時是否關閉文件?如果是這樣,如果生產者進程仍在生產,試圖用排它鎖打開消費者進程中的文件將失敗。
在linux下使用rsync命令複製文件,所以我相信它。好主意,現在就試試吧。 –
你能寫一個例子來說明這個過程嗎? –
這不是一個非常有用的正確答案:( –
我不認爲有一個通用的解決方案。尋找文件大小是錯誤的,因爲某些應用程序可以在任何寫入調用之前設置文件大小。其中一種可能性是使用鎖定。這將要求作者累積寫鎖(或獨佔鎖)。如果你不能修改編寫器,那麼你可以使用OS提供的工具,比如Linux上的fuser來查看是否存在仍然可以訪問文件的進程。
如果您打算在單一平臺上使用此代碼,您可以使用NIO's FileLock facility。但請仔細閱讀文檔,並注意在許多平臺上,鎖只是諮詢。
另一種方法是讓一個進程用您的進程無法識別的名稱寫入該文件,然後在寫入完成時將該文件重命名爲可識別的名稱。在大多數平臺上,如果源和目標是相同的文件系統卷,則重命名操作是原子操作。
好的一點,謝謝,如果java沒有成功,就做到這一點,在某些情況下,改變生產者行爲有點困難 –
我得到了解決工作:
private boolean isCompletelyWritten(File file) {
RandomAccessFile stream = null;
try {
stream = new RandomAccessFile(file, "rw");
return true;
} catch (Exception e) {
log.info("Skipping file " + file.getName() + " for this iteration due it's not completely written");
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
log.error("Exception during closing file " + file.getName());
}
}
}
return false;
}
感謝@cklab和@Will和所有其他人誰提出的「排它鎖」的方式來看待。我只是在這裏發佈代碼以使其他感興趣的人使用它。我相信@tigran提出的重命名解決方案也可行,但純Java解決方案對我來說更可取。
P.S.最初我用FileOutputStream
而不是RandomAccessFile
,但它鎖定正在寫入的文件。
如果你可以使用Java 1.7,看看NIO的工具,特別java.nio.channels.FileChannel
here是鎖定的文件,閱讀它的一個例子。
我已經在過去使用此方案與Windows一個簡單的解決方案是使用boolean File.renameTo(File)
並嘗試將原始文件移動到一個單獨的臨時文件夾:
如果success
是false
,那麼potentiallyIncompleteFile
仍在寫入。
Windows用戶的好建議,但它不是平臺不可知的。在Linux/Unix上,您可以刪除並重命名其他進程仍然打開的文件。 –
這就是爲什麼我的答案說「與Windows」,而不是「所有系統」。 – JoshDM
您是否考慮過使用文件鎖? – cklab
謝謝。檢查這個。我們能否確定鎖定總是通過寫入過程創建的? –
好吧,這個概念是,如果你試圖獲得一個鎖,你應該得到一個例外。我剛剛遇到了這個:http://docs.oracle.com/javase/7/docs/api/java/io/File。html#canWrite%28%29從來沒有使用過它,但你可以試試看它是如何工作的。看起來很有趣。 – cklab