posts - 59, comments - 244, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          java實(shí)現(xiàn)文件監(jiān)控

          Posted on 2011-01-09 16:32 penngo 閱讀(14526) 評論(10)  編輯  收藏 所屬分類: Java

          java本身不能直接監(jiān)聽系統(tǒng)的文件操作事件,不過可以先編寫C/C++調(diào)用操作系統(tǒng)的API監(jiān)聽文件,再通過jni調(diào)用的方式實(shí)現(xiàn)。限于本人的C/C++水平有限,沒有用C/C++實(shí)現(xiàn)該接口,而且已有開源組件JNotify實(shí)現(xiàn)了這個(gè)功能,本文例子使用JNotify。

          public class MainFrame extends JFrame {

              
          private JPanel contentPane;
              
          private JTextField textField;
              
          private JTextArea textArea;

              
          public static void main(String[] args) {
                  EventQueue.invokeLater(
          new Runnable() {
                      
          public void run() {
                          
          try {
                              MainFrame frame 
          = new MainFrame();
                              frame.setVisible(
          true);
                          } 
          catch (Exception e) {
                              e.printStackTrace();
                          }
                      }
                  });
              }

              
          public MainFrame() {
                  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  setBounds(
          100100543300);
                  contentPane 
          = new JPanel();
                  contentPane.setBorder(
          new EmptyBorder(5555));
                  setContentPane(contentPane);
                  contentPane.setLayout(
          null);

                  JLabel label 
          = new JLabel("監(jiān)控路徑:");
                  label.setBounds(
          33206515);
                  contentPane.add(label);

                  textField 
          = new JTextField("D:/");
                  textField.setBounds(
          901621921);
                  contentPane.add(textField);
                  textField.setColumns(
          10);

                  JButton button 
          = new JButton("開始監(jiān)控");
                  button.addActionListener(
          new ActionListener() {
                      
          public void actionPerformed(ActionEvent e) {
                          
          try {
                              addWatch();
                          } 
          catch (Exception ex) {
                              ex.printStackTrace();
                          }
                      }
                  });
                  button.setBounds(
          319169323);
                  contentPane.add(button);

                  textArea 
          = new JTextArea();
                  JScrollPane scrollPane 
          = new JScrollPane(textArea);
                  scrollPane.setBounds(
          3345480207);
                  contentPane.add(scrollPane);
              }

              
          public void addWatch() throws Exception {
                  String path 
          = textField.getText();
                  
          int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED
                          
          | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
                  
          boolean watchSubtree = true;
                  
          //添加文件監(jiān)聽
                  int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());
              }

              
          class Listener implements JNotifyListener {
                  
          public void fileRenamed(int wd, String rootPath, String oldName,
                          String newName) {
                      textArea.append(
          "文件:" + rootPath + " : " + oldName + " 重命名為: "
                              
          + newName + "\n");
                  }

                  
          public void fileModified(int wd, String rootPath, String name) {
                      textArea.append(
          "文件修改 " + rootPath + " : " + name + "\n");
                  }

                  
          public void fileDeleted(int wd, String rootPath, String name) {
                      textArea.append(
          "刪除文件: " + rootPath + " : " + name + "\n");
                  }

                  
          public void fileCreated(int wd, String rootPath, String name) {
                      textArea.append(
          "新建文件: " + rootPath + " : " + name + "\n");
                  }
              }
          }

          運(yùn)行效果:
          在D盤新建一個(gè)文件和修改文件名操作。
          http://www.aygfsteel.com/pengo

          附件:源碼

          評論

          # re: java實(shí)現(xiàn)文件監(jiān)控[未登錄]  回復(fù)  更多評論   

          2011-01-10 23:35 by semmy
          無法監(jiān)控到打開文件和文件夾,只能監(jiān)控到增、刪、改。

          # re: java實(shí)現(xiàn)文件監(jiān)控[未登錄]  回復(fù)  更多評論   

          2011-01-10 23:40 by semmy
          不知道有沒有辦法監(jiān)控到打開文件

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2011-01-11 00:32 by pengo
          JNotify現(xiàn)在的版本是沒有監(jiān)控打開文件,如果你用的是window系統(tǒng),可以查下window api,看看有監(jiān)控文件打開的API,有的話用C/C++寫好編譯成DLL,再用通過java的jni或jna調(diào)用就行了。

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2011-01-13 11:16 by nihao
          我在使用JNotify的時(shí)候發(fā)現(xiàn)
          創(chuàng)建一個(gè)文件會同時(shí)觸發(fā)一個(gè)Create事件和3-4個(gè)Modify事件
          重命名一個(gè)文件的時(shí)候也同時(shí)出發(fā)一個(gè)Rename事件和一個(gè)Modify事件
          修改一個(gè)文件的時(shí)候會觸發(fā)3-4個(gè)Modify事件
          我的MASK是
          JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_RENAMED| JNotify.FILE_MODIFIED

          不知道博主是否有遇到過這種問題,謝謝

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2011-01-13 11:18 by nihao
          順便也把我的源代碼貼出來吧:

          package notify;

          import net.contentobjects.jnotify.*;

          class Listener implements JNotifyListener{
          public void fileRenamed(int wd, String rootPath, String oldName, String newName){
          System.out.println("renamed " + rootPath + " : " + oldName + " -> " + newName);
          }
          public void fileModified(int wd, String rootPath, String name){
          System.out.println("modified " + rootPath + " : " + name);
          }
          public void fileDeleted(int wd, String rootPath, String name){
          System.out.println("deleted " + rootPath + " : " + name);
          }
          public void fileCreated(int wd, String rootPath, String name){
          System.out.println("created " + rootPath + " : " + name);
          }
          public void print(String msg){
          System.err.println(msg);
          }
          }

          public class Main {

          public static void main(String[] args) throws JNotifyException {
          // TODO code application logic here
          String path = "D:/test";
          int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_RENAMED
          | JNotify.FILE_MODIFIED
          ;
          boolean watchSubtree = true;
          int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());
          try {
          Thread.sleep(1000000);
          } catch (InterruptedException e1) {
          }
          JNotify.removeWatch(watchID);
          }
          }

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2011-01-13 23:19 by pengo
          創(chuàng)建的時(shí)候不會,重命名和修改好像是一樣。

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2012-09-11 16:15 by wzp
          @semmy
          (只試過linux下的,windows下也差不多應(yīng)該)
          可以添加打開文件的監(jiān)聽
          在源碼中的JNotifyListener接口中添加open(),然后在JNotifyAdapterLinux(windows的改JNotifyAdapterWin32)類中,添加實(shí)現(xiàn)
          由于源碼中已經(jīng)存在 IN_OPEN = 0x00000020; /* File was opened */的定義,所以可以直接調(diào)用它,這個(gè)就是linux的打開事件。
          代碼如下:
          在public int addWatch(String path, int mask, boolean watchSubtree, JNotifyListener listener)中添加:
          //訪問文件
          if ((mask & JNotify.FILE_OPENED) != 0)
          {
          linuxMask |= JNotify_linux.IN_OPEN;
          }

          在protected void notifyChangeEvent(String name, int linuxWd, int linuxMask, int cookie)中添加 (具體位置自己讀代碼,應(yīng)該很容易分析出來的)
          //文件訪問
          else
          if ((linuxMask & JNotify_linux.IN_OPEN) != 0)
          {
          watchData.notifyFileOpened(name);
          }
          最后在下面添加方法
          public void notifyFileOpened(String name)
          {
          String outRoot = getOutRoot();
          String outName = getOutName(name);
          _listener.fileOpenfied(getParentWatchID(), outRoot, outName);
          }
          這個(gè)只是linux中的測試代碼,仍然存在很多問題。

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2015-06-29 10:02 by xugy
          @nihao
          你應(yīng)該是循環(huán)中進(jìn)行了多次 JNotify.addWatch 吧?
          在循環(huán)結(jié)束前 JNotify.removeWatch(watchID); 應(yīng)該就好了!

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2016-04-26 19:47 by summer_seo
          怎么在最后追加時(shí)間呢

          # re: java實(shí)現(xiàn)文件監(jiān)控  回復(fù)  更多評論   

          2016-04-26 19:48 by summer_seo
          怎么在追加信息里加入時(shí)間
          主站蜘蛛池模板: 宝山区| 巴楚县| 河北区| 连山| 京山县| 苍溪县| 柳江县| 南川市| 教育| 玛多县| 宣化县| 宝鸡市| 砚山县| 乐昌市| 叙永县| 洪湖市| 明溪县| 杭锦旗| 祥云县| 宁都县| 元谋县| 柳河县| 鹤壁市| 龙陵县| 股票| 丰都县| 丰镇市| 汕尾市| 新绛县| 鄄城县| 文昌市| 新竹县| 沧源| 新巴尔虎右旗| 汾西县| 通化市| 铜山县| 秦皇岛市| 卢湾区| 拜城县| 平江县|