我正在研究應該有效(並遞歸)將文件/目錄從源位置複製到目標位置的Java過程。在Java中使用文件鎖複製文件
要做到這一點,我想:
- 創建鎖
- 如果目標文件不存在,複製
- 否則如果目標文件不同的是,將它複製
- 否則它們是一樣的,所以什麼都不做
- 釋放鎖
要檢查內容是否相同,我正計劃使用Apache Commons IO FileUtils
方法contentsEqual(...)
。爲了進行復制,我打算使用Apache Commons IO FileUtils
方法copyFile(...)
。
所以,我想出了代碼是(這僅僅是文件,目錄遞歸向下處理此方法的文件):
private static void checkAndUpdateFile(File src, File dest) throws IOException {
FileOutputStream out = new FileOutputStream(dest);
FileChannel channel = out.getChannel();
FileLock lock = channel.lock();
if (!dest.exists()) {
FileUtils.copyFile(src, out);
} else if (!FileUtils.contentEquals(src, dest)) {
FileUtils.copyFile(src, out);
}
lock.release();
channel.close();
out.close();
}
這確實的文件鎖定(偉大的),並複製文件(超級)。
但是,每當它複製文件時,它都會將複製文件的上次修改時間戳設置爲複製時間。這意味着後續調用FileUtils.contentEquals(src, dest)
繼續返回false
,因此文件被重新複製。
我真的很喜歡類似於FileUtils.copyFile(src, dest, true)
,它保留了文件時間戳 - 並且從調用FileUtils.contentEquals(src, dest)
變爲true。這將要求鎖定在File
上,而不是FileOutputStream
,否則將調用FileUtils.copyFile(src, dest, true)
失敗並拋出異常,因爲文件被鎖定。
或者,我考慮做FileUtils.copyFile(src, dest, true)
方法所做的事,即調用dest.setLastModified(src.lastModified())
。但是,這將不得不在鎖釋放後調用,如果同一進程已被同時執行超過一次,則可能會導致問題。
我也考慮過把鎖放在源文件上的ide,但是這並沒有幫助,因爲我不得不把它放在FileInputStream
上,我想通過File
到FileUtils.copyFile(src, dest)
。
所以:
- 有沒有更簡單的方法來實現什麼,我試圖做的?
- 是否可以鎖定文件而不是文件的派生?
- 解決此問題的最佳方法是什麼?
- 即我只需要編寫我自己的方法來處理這部分問題? (可能
copyFile(...)
)
- 即我只需要編寫我自己的方法來處理這部分問題? (可能
這是一個不錯的主意,但如何與文件鎖定一起工作?我無法在'ByteSource'上獲得'FileLock',我無法從一個文件創建一個ByteSource,同時存在一個單獨的鎖,並且將'ByteSource'放在鎖之外是沒有意義的 - 也就是說,在問題上,這在功能上等同於使用'apache.commons.io.FileUtils' – amaidment
@amaidment,您可以從文件http://docs.oracle.com/javase/7/docs/api/java/io/File.html獲取URL #toURL%28%29。一旦你鎖定文件獲取URL並獲得輸入字節源和目標文件相同 – Makky
不,這是行不通的。當代碼調用'inByte.contentEquals(outByte)'時,它試圖訪問一個已被鎖定的文件,並以「IOException異常:進程無法訪問文件,因爲另一個進程鎖定了一部分文件」 – amaidment