JAVA监控目录

 

JAVA监控目录

1.      编写DLL

编写DLL文件是重点,这个DLL得作用就是用C++去监控某个目录,而具体得接口则暴露给JAVAJAVA负责调用就OK

原理如下:

根据JAVA传来得需要监视得目录路径,得到这个目录得句柄,同时新建一个线程去监控这个目录发生得一切,而具体得监视是由库函数ReadDirectoryChangesW完成得,它能得到目录修改的信息,然后将其打印出来!

但是在开发过程中,我遇到了很多很多的问题,主要有两个

1.      VC++不识别ReadDirectoryChanges,上网搜索很多的方法都没有成功,直到一位高人指导,解决这个问题,需要两个方面

1. 头部信息

#include "stdafx.h"

#define _WIN32_WINNT 0x0500//必须再windows.h前才有效

#include <windows.h>

2. 设置一些必要的参数

Project-Setting->C/C++->Preprocessor definitions->加上_WIN32_WINNT=0x0500,WINVER=0x0500那么就OK

2.      JAVA传递给C++会产生乱码,可能是我的String匹配有错,C++string难道不是用JAVAString匹配吗?这个问题我还是没有搞清楚,期待解决,最终我为了试验成功,就再DLL得代码中,默认指定了我得测试路径d:/watch

 

 

下面是具体得C++监控类源码

#include "stdafx.h"

#define _WIN32_WINNT 0x0500

#include <Winbase.h>

 

#include <string>

#include <cassert>

#include <conio.h>

#include <iostream>

using namespace std;

 

enum ACTION { ADDED=1, REMOVED=2, MODIFIED=3, RENAMED=4 };//判断文件操作类型得枚举

/*

*处理操作信息得函数

*/

void __stdcall MyDeal( ACTION act, std::string filename1, std::string filename2 )

{

    switch( act )

    {

    case ADDED:

        cout << "Added    - " << filename1 << endl;

        break;

    case REMOVED:

        cout << "Removed  - " << filename1 << endl;

        break;

    case MODIFIED:

        cout << "Modified - " << filename1 << endl;

        break;

    case RENAMED:

        cout << "Rename   - " << filename1 << " " << filename2 << endl;

        break;

    }

};

class FileSystemWatcher

{

public:

    typedef void (__stdcall *LPDEALFUNCTION)( ACTION act, std::string filename1, std::string filename2 );

 

    bool Run( std::string path)

    {

        WatchedDir = path;

      

        DealFun = MyDeal;

      

        DWORD ThreadId;

              cout<<"创建线程"<<endl;

        hThread=CreateThread( NULL,0,Routine,this,0,&ThreadId );

              cout<<"创建结束"<<endl;

              if (NULL!=hThread) {

                     cout<<"创建线程成功"<<endl;

              } else {

                     cout<<"创建线程失败"<<endl;

              }

        return NULL!=hThread;

}

 

//释放资源

    void Close()

    {

        if( NULL != hThread )

        {

            TerminateThread( hThread, 0 );

            hThread = NULL;

        }

        if( INVALID_HANDLE_VALUE != hDir )

        {

            CloseHandle( hDir );

            hDir = INVALID_HANDLE_VALUE;

        }

    }

    FileSystemWatcher() : DealFun(NULL), hThread(NULL), hDir(INVALID_HANDLE_VALUE)

    {

    }

    ~FileSystemWatcher()

    {

        Close();

    }

 

private:

    std::string WatchedDir;

    LPDEALFUNCTION DealFun;

    HANDLE hThread;

    HANDLE hDir;

private:

    FileSystemWatcher( const FileSystemWatcher& );

    FileSystemWatcher operator=( const FileSystemWatcher );

private:

    static DWORD WINAPI Routine( LPVOID lParam )

    {

              cout<<"开始执行线程"<<endl;

        FileSystemWatcher* obj = (FileSystemWatcher*)lParam;

              cout<<"要观察得目录"<<obj->WatchedDir<<endl;

              cout<<direc<<endl;

        obj->hDir = CreateFile(

            obj->WatchedDir.c_str(),

            GENERIC_READ|GENERIC_WRITE,

            FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,

            NULL,

            OPEN_EXISTING,

            FILE_FLAG_BACKUP_SEMANTICS,

            NULL

        );

                     cout<<"创建文件"<<endl;

                     if( INVALID_HANDLE_VALUE == obj->hDir ) {

                            cout<<"无效值"<<endl;

                            return false;

                     }

        char buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ];

        FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf;

        DWORD BytesReturned;

cout<<"读取信息"<<endl;

        while(true)

        {

                    

            if( ReadDirectoryChangesW( obj->hDir,

                pNotify,

                sizeof(buf),

                true,

                FILE_NOTIFY_CHANGE_FILE_NAME|

                FILE_NOTIFY_CHANGE_DIR_NAME|

                FILE_NOTIFY_CHANGE_ATTRIBUTES|

                FILE_NOTIFY_CHANGE_SIZE|

                FILE_NOTIFY_CHANGE_LAST_WRITE|

                FILE_NOTIFY_CHANGE_LAST_ACCESS|

                FILE_NOTIFY_CHANGE_CREATION|

                FILE_NOTIFY_CHANGE_SECURITY,

                &BytesReturned,

                NULL,

                NULL ) )

            {

                            cout<<"读取信息成功"<<endl;

                char tmp[MAX_PATH], str1[MAX_PATH], str2[MAX_PATH];

                memset( tmp, 0, sizeof(tmp) );

                WideCharToMultiByte( CP_ACP,0,pNotify->FileName,pNotify->FileNameLength/2,tmp,99,NULL,NULL );

                strcpy( str1, tmp );

 

                if( 0 != pNotify->NextEntryOffset )

                {

                    PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify+pNotify->NextEntryOffset);

                    memset( tmp, 0, sizeof(tmp) );

                    WideCharToMultiByte( CP_ACP,0,p->FileName,p->FileNameLength/2,tmp,99,NULL,NULL );

                    strcpy( str2, tmp );

                }

 

                obj->DealFun( (ACTION)pNotify->Action, str1, str2 );

            }

            else

            {

                  cout<<"读取信息失败"<<endl;

                break;

            }

        }

 

        return 0;

    }

};

 

有了这个源码(这个源码需要放到.h文件中,负责无法加载使用)以后,就是暴露接口让JAVA调用了,下面是类代码

// FuckYouToDie.cpp : Defines the entry point for the DLL application.

//

//setting->C/C++  

 // 中加上_WIN32_WINNT=0x0500,WINVER=0x0500

//

#include "stdafx.h"

#include "Fuck.h"//是上面得代码得头文件

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                    )

{

    return TRUE;

}//默认得入口函数,不用管

 

extern "C" bool __declspec(dllexport) Run() {

       FileSystemWatcher b;

       cout<<"建立B对象"<<endl;

       bool r =  b.Run("d:/watch");

       char c;

       cin>>c;

       while(c != 'q'){

              cin>>c;

       }

       return r;

}

 

 

然后进行编译链接,就获得了对于得.dll文件,然后接下来就是用JAVA调用了

 

 

2.      JAVAJNA框架去调用

用这个框架调用C++真的是很简单,只需要两个类,一个类

是接口

import com.sun.jna.Library;

 

public interface DLLD extends Library {

 

       boolean Run();

}

继承Library,然后里面得方法要和C++暴露给你得接口一一对应

另外一个就是调用类了

 

import com.sun.jna.Native;

 

public class DLLDTest {

 

       public static void main(String[] args) {

 

              DLLD loadLibrary = (DLLD) Native.loadLibrary(

                            "E:/网络试验/Tt/src/FuckYouToDie.dll", DLLD.class);

              System.out.println(loadLibrary.Run());

             

       }

}

 

注意看代码,JAVA数据类型,要和C++得一一对应才行,然后会找到函数,比如JAVA得int对c++得int,java得char对c++得w_char等,要注意匹配,方法名需要一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值