問題:
存在兩個文件目錄,且稱之為源目錄和目標目錄,需要不定期將源目錄和目標目錄進行同步。
兩種同步方法:
1 采用從源目錄到目標目錄的完全拷貝覆蓋。顯而易見的缺點,當文件目錄中文件多、體積大時拷貝過程時間消耗極大。
2 采用從源目錄到目標目錄的變更集拷貝覆蓋。避免了大量拷貝的IO耗時操作,但產生了新的問題:如何獲取變更信息?
新問題:
如何監控一個文件目錄的變更情況。
還是兩種方法:
1 掃描式。不定期對源目錄進行輪循掃描,獲取變更。弱點:同樣的,文件目錄中文件多、體積大時掃描耗時久,響應也慢。
2 事件驅動式。當源目錄發生變更時,拋出變更事件。JNI和JNotify可以提供支持,據說JDK 7內置支持,不過咱公司還沒用上。
JNotify相關介紹:
JNotify:http://jnotify.sourceforge.net/,通過JNI技術,讓Java代碼可以實時的監控制定文件夾內文件的變動信息,支持Linux/Windows/MacOS。
JNotify的准備:
在使用JNotify之前,你需要“安裝”一下JNotify,分為兩個部分:jnotify-lib-0.93.jar和jnotify.dll/jnotify_64bit.dll。
jar自然設計類路徑即可,dll則放置在java.library.path所指向的文件夾中。
java.library.path的值可以在java程序中通過如下語句:
System.getProperty("java.library.path")
查看,一般在windows下放在[jre安裝目錄]/bin下即可;
也可以手動指定程序的啟動參數:
java -Djava.library.path=[dll路徑]
的方法來達到目的;
也可以在java程序中通過如下語句:
System.load("xxxx/jnotify.dll")
來加載dll,這個可以方便程序打包。
JNotify使用了JNI技術來調用系統的本地庫(Win下的是dll文件,Linux下是so文件),dll放置不正確,會有如下報錯:
java.lang.UnsatisfiedLinkError: no jnotify in java.library.path
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.loadLibrary0(Unknown Source)
at java.lang.System.loadLibrary(Unknown Source)
at net.contentobjects.jnotify.win32.JNotify_win32.<clinit>(Unknown Source)
at net.contentobjects.jnotify.win32.JNotifyAdapterWin32.<init>(Unknown Source)
JNotify使用示例:
- package com.dancen.test;
-
-
- import net.contentobjects.jnotify.JNotify;
- import net.contentobjects.jnotify.JNotifyListener;
-
-
- public class FileWatch
- {
- public static void main(String[] args)
- {
- try
- {
- new FileWatch().sampleTest();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
-
- public void sampleTest() throws Exception
- {
- // path to watch
- String path = "D:\\download";
-
-
- // watch mask, specify events you care about,
- // or JNotify.FILE_ANY for all events.
- int mask = JNotify.FILE_CREATED
- | JNotify.FILE_DELETED
- | JNotify.FILE_MODIFIED
- | JNotify.FILE_RENAMED;
-
-
- // watch subtree?
- boolean watchSubtree = true;
-
-
- // add actual watch
- int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());
-
-
- // sleep a little, the application will exit if you
- // don't (watching is asynchronous), depending on your
- // application, this may not be required
- Thread.sleep(1000000);
-
-
- // to remove watch the watch
- boolean res = JNotify.removeWatch(watchID);
-
- if (!res)
- {
- // invalid watch ID specified.
- }
- }
-
-
- class Listener implements JNotifyListener
- {
- public void fileRenamed(int wd, String rootPath, String oldName, String newName)
- {
- print("renamed " + rootPath + " : " + oldName + " -> " + newName);
- }
-
-
- public void fileModified(int wd, String rootPath, String name)
- {
- print("modified " + rootPath + " : " + name);
- }
-
-
- public void fileDeleted(int wd, String rootPath, String name)
- {
- print("deleted " + rootPath + " : " + name);
- }
-
-
- public void fileCreated(int wd, String rootPath, String name)
- {
- print("created " + rootPath + " : " + name);
- }
-
-
- void print(String msg)
- {
- System.err.println(msg);
- }
- }
- }