做这个小项目的目的主要也是为了项目小组成员能更好地一致工作。现在一般做项目都是通过CVS将人家的代码更新下来,在自己的机子上把应用给跑起来,但如果我们做的是web开发,那么可以试着将大家各自的“服务器”统一到一台服务器上,比如,CVS提交上192.168.0.1上后,打开网页192.168.0.1能自动体现出来。现在的问题是,如果简单在服务器上把IIS或者TOMCAT之类的目录指到CVS仓库上是没用的,因为存在CVS仓库上的文件都是经过CVS的方式储存的,拿出来不能直接跑起来的。于是我就有了做这个自动化工作的想法。
CVS提交——》服务器监控到CVS仓库变化——》下载更新到IIS或者TOMCAT指定的目录——》小组成员刷新网页
| |
|________________________小组成员所需做的_______________________________________|
这里有2个重点所以,一、监控文件变化 二、CVS操作
对于CVS操作,JAVA用javacvs开源项目可以非常轻松搞定,但是对于文件的变化监控,考虑到效率java非常难做,因为java只能主动去提取文件系统的变化,而不能让文件系统的变化来通知java,所以这个while循环只能依赖线程的sleep。 所幸的是,windows API给我们提供了一套非常好的回调机制用来监控文件系统
FindFirstChangeNotification
FindNextChangeNotification
FindCloseChangeNotification
在MSDN上有很详细的描述,这里我把MSDN上的例子拿出来
嗯……看来完全符合我们的要求。好了,现在开始从JAVA端开始写
JNI的文章网上都有,一般都是编写native接口,生产.h头文件,再写.cpp实现,编译成DLL……
let‘s go……
接着我们编译好,用javah生成.h文件
把JDK里的inlude 文件内的文件包含到工程里,引入刚才生成的头文件
头文件代码是自动生成的,如下:
下面是自己编写的 filewatcher.cpp
编译生成 filewatcher.dll
可以了,我们开始做单元测试吧:
可以发现,在第一个方法那里停住了,也就是说进入了监控状态,我们在D盘下写入一个文件后,可以发现测试自动全部完成。
监控的状态如下
CVS提交——》服务器监控到CVS仓库变化——》下载更新到IIS或者TOMCAT指定的目录——》小组成员刷新网页
| |
|________________________小组成员所需做的_______________________________________|
这里有2个重点所以,一、监控文件变化 二、CVS操作
对于CVS操作,JAVA用javacvs开源项目可以非常轻松搞定,但是对于文件的变化监控,考虑到效率java非常难做,因为java只能主动去提取文件系统的变化,而不能让文件系统的变化来通知java,所以这个while循环只能依赖线程的sleep。 所幸的是,windows API给我们提供了一套非常好的回调机制用来监控文件系统
FindFirstChangeNotification
FindNextChangeNotification
FindCloseChangeNotification
在MSDN上有很详细的描述,这里我把MSDN上的例子拿出来
#include
<
windows.h
>
#include < stdlib.h >
#include < stdio.h >
#include < tchar.h >
void RefreshDirectory(LPTSTR);
void RefreshTree(LPTSTR);
void WatchDirectory(LPTSTR lpDir)
{
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
TCHAR lpDrive[4];
TCHAR lpFile[_MAX_FNAME];
TCHAR lpExt[_MAX_EXT];
_tsplitpath(lpDir, lpDrive, NULL, lpFile, lpExt);
lpDrive[2] = (TCHAR)'/';
lpDrive[3] = (TCHAR)'';
// Watch the directory for file creation and deletion.
dwChangeHandles[0] = FindFirstChangeNotification(
lpDir, // directory to watch
FALSE, // do not watch subtree
FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());
// Watch the subtree for directory creation and deletion.
dwChangeHandles[1] = FindFirstChangeNotification(
lpDrive, // directory to watch
TRUE, // watch the subtree
FILE_NOTIFY_CHANGE_DIR_NAME); // watch dir. name changes
if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());
// Change notification is set. Now wait on both notification
// handles and refresh accordingly.
while (TRUE)
{
// Wait for notification.
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles,
FALSE, INFINITE);
switch (dwWaitStatus)
{
case WAIT_OBJECT_0:
// A file was created or deleted in the directory.
// Refresh this directory and restart the notification.
RefreshDirectory(lpDir);
if ( FindNextChangeNotification(
dwChangeHandles[0]) == FALSE )
ExitProcess(GetLastError());
break;
case WAIT_OBJECT_0 + 1:
// A directory was created or deleted in the subtree.
// Refresh the tree and restart the notification.
RefreshTree(lpDrive);
if (FindNextChangeNotification(
dwChangeHandles[1]) == FALSE)
ExitProcess(GetLastError());
break;
default:
ExitProcess(GetLastError());
}
}
}
void RefreshDirectory(LPTSTR lpDir)
{
_tprintf(TEXT("Refresh the directory (%s). "), lpDir);
}
void RefreshTree(LPTSTR lpDrive)
{
_tprintf(TEXT("Refresh the directory tree (%s). "), lpDrive);
}
#include < stdlib.h >
#include < stdio.h >
#include < tchar.h >
void RefreshDirectory(LPTSTR);
void RefreshTree(LPTSTR);
void WatchDirectory(LPTSTR lpDir)
{
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
TCHAR lpDrive[4];
TCHAR lpFile[_MAX_FNAME];
TCHAR lpExt[_MAX_EXT];
_tsplitpath(lpDir, lpDrive, NULL, lpFile, lpExt);
lpDrive[2] = (TCHAR)'/';
lpDrive[3] = (TCHAR)'';
// Watch the directory for file creation and deletion.
dwChangeHandles[0] = FindFirstChangeNotification(
lpDir, // directory to watch
FALSE, // do not watch subtree
FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());
// Watch the subtree for directory creation and deletion.
dwChangeHandles[1] = FindFirstChangeNotification(
lpDrive, // directory to watch
TRUE, // watch the subtree
FILE_NOTIFY_CHANGE_DIR_NAME); // watch dir. name changes
if (dwChangeHandles[1] == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());
// Change notification is set. Now wait on both notification
// handles and refresh accordingly.
while (TRUE)
{
// Wait for notification.
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles,
FALSE, INFINITE);
switch (dwWaitStatus)
{
case WAIT_OBJECT_0:
// A file was created or deleted in the directory.
// Refresh this directory and restart the notification.
RefreshDirectory(lpDir);
if ( FindNextChangeNotification(
dwChangeHandles[0]) == FALSE )
ExitProcess(GetLastError());
break;
case WAIT_OBJECT_0 + 1:
// A directory was created or deleted in the subtree.
// Refresh the tree and restart the notification.
RefreshTree(lpDrive);
if (FindNextChangeNotification(
dwChangeHandles[1]) == FALSE)
ExitProcess(GetLastError());
break;
default:
ExitProcess(GetLastError());
}
}
}
void RefreshDirectory(LPTSTR lpDir)
{
_tprintf(TEXT("Refresh the directory (%s). "), lpDir);
}
void RefreshTree(LPTSTR lpDrive)
{
_tprintf(TEXT("Refresh the directory tree (%s). "), lpDrive);
}
嗯……看来完全符合我们的要求。好了,现在开始从JAVA端开始写
JNI的文章网上都有,一般都是编写native接口,生产.h头文件,再写.cpp实现,编译成DLL……
let‘s go……
package
wxy.tool.filewatcher;
public final class FileWatcherNative {
static {
System.loadLibrary("FileWatcher");
}
/**
* HANDLE FindFirstChangeNotification( LPCTSTR lpPathName, BOOL
* bWatchSubtree, DWORD dwNotifyFilter );
* 用来得到句柄
*/
static native long FindFirstChangeNotification(String lpPathName,
boolean bWatchSubtree, int dwNotifyFilter) throws Exception;
/**
* BOOL FindNextChangeNotification( HANDLE hChangeHandle );
* 开始监控句柄
*/
static native void FindNextChangeNotification(long hChangeHandle)
throws Exception;
/**
* BOOL FindCloseChangeNotification( HANDLE hChangeHandle );
* 关闭监控
*/
static native void FindCloseChangeNotification(long hChangeHandle)
throws Exception;
/**
* DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
*
* 等待这个句柄的反应
*
* 注意,这里我们要让它无穷等待,所以dwMilliseconds要设置为无穷,但是java里的无穷
* 与c里的无穷是不一样的,java里,int类型的正无穷代表2的31次方-1,负无穷代表
* -2的31次方,有正负之分,而dwMilliseconds数据类型为unsigned long仅仅代表了正数
* 概念,所以我们表示成0xFFFFFFFF就可以了,其实相当于-1,这里我们干脆把这个类型定义死
*/
static native int WaitForSingleObject(long hHandle,
int dwTimeoutMilliseconds);
static final int INFINITE = 0xFFFFFFFF;
/**
* 下面三个参数都是代表WaitForSingleObject的返回值,第二个是正常返回的
*/
static final int WAIT_ABANDONED = 0x00000080;
static final int WAIT_OBJECT_0 = 0x00000000;
static final int WAIT_TIMEOUT = 0x00000102;
}
public final class FileWatcherNative {
static {
System.loadLibrary("FileWatcher");
}
/**
* HANDLE FindFirstChangeNotification( LPCTSTR lpPathName, BOOL
* bWatchSubtree, DWORD dwNotifyFilter );
* 用来得到句柄
*/
static native long FindFirstChangeNotification(String lpPathName,
boolean bWatchSubtree, int dwNotifyFilter) throws Exception;
/**
* BOOL FindNextChangeNotification( HANDLE hChangeHandle );
* 开始监控句柄
*/
static native void FindNextChangeNotification(long hChangeHandle)
throws Exception;
/**
* BOOL FindCloseChangeNotification( HANDLE hChangeHandle );
* 关闭监控
*/
static native void FindCloseChangeNotification(long hChangeHandle)
throws Exception;
/**
* DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
*
* 等待这个句柄的反应
*
* 注意,这里我们要让它无穷等待,所以dwMilliseconds要设置为无穷,但是java里的无穷
* 与c里的无穷是不一样的,java里,int类型的正无穷代表2的31次方-1,负无穷代表
* -2的31次方,有正负之分,而dwMilliseconds数据类型为unsigned long仅仅代表了正数
* 概念,所以我们表示成0xFFFFFFFF就可以了,其实相当于-1,这里我们干脆把这个类型定义死
*/
static native int WaitForSingleObject(long hHandle,
int dwTimeoutMilliseconds);
static final int INFINITE = 0xFFFFFFFF;
/**
* 下面三个参数都是代表WaitForSingleObject的返回值,第二个是正常返回的
*/
static final int WAIT_ABANDONED = 0x00000080;
static final int WAIT_OBJECT_0 = 0x00000000;
static final int WAIT_TIMEOUT = 0x00000102;
}
接着我们编译好,用javah生成.h文件
把JDK里的inlude 文件内的文件包含到工程里,引入刚才生成的头文件
头文件代码是自动生成的,如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include " jni.h "
/* Header for class wxy_tool_filewatcher_FileWatcherNative */
#ifndef _Included_wxy_tool_filewatcher_FileWatcherNative
#define _Included_wxy_tool_filewatcher_FileWatcherNative
#ifdef __cplusplus
extern " C " {
#endif
#undef wxy_tool_filewatcher_FileWatcherNative_INFINITE
#define wxy_tool_filewatcher_FileWatcherNative_INFINITE -1L
#undef wxy_tool_filewatcher_FileWatcherNative_WAIT_ABANDONED
#define wxy_tool_filewatcher_FileWatcherNative_WAIT_ABANDONED 128L
#undef wxy_tool_filewatcher_FileWatcherNative_WAIT_OBJECT_0
#define wxy_tool_filewatcher_FileWatcherNative_WAIT_OBJECT_0 0L
#undef wxy_tool_filewatcher_FileWatcherNative_WAIT_TIMEOUT
#define wxy_tool_filewatcher_FileWatcherNative_WAIT_TIMEOUT 258L
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: FindFirstChangeNotification
* Signature: (Ljava/lang/String;ZI)J
*/
JNIEXPORT jlong JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindFirstChangeNotification
(JNIEnv *, jclass, jstring, jboolean, jint);
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: FindNextChangeNotification
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindNextChangeNotification
(JNIEnv *, jclass, jlong);
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: FindCloseChangeNotification
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindCloseChangeNotification
(JNIEnv *, jclass, jlong);
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: WaitForSingleObject
* Signature: (JI)I
*/
JNIEXPORT jint JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_WaitForSingleObject
(JNIEnv *, jclass, jlong, jint);
#ifdef __cplusplus
}
#endif
#endif
#include " jni.h "
/* Header for class wxy_tool_filewatcher_FileWatcherNative */
#ifndef _Included_wxy_tool_filewatcher_FileWatcherNative
#define _Included_wxy_tool_filewatcher_FileWatcherNative
#ifdef __cplusplus
extern " C " {
#endif
#undef wxy_tool_filewatcher_FileWatcherNative_INFINITE
#define wxy_tool_filewatcher_FileWatcherNative_INFINITE -1L
#undef wxy_tool_filewatcher_FileWatcherNative_WAIT_ABANDONED
#define wxy_tool_filewatcher_FileWatcherNative_WAIT_ABANDONED 128L
#undef wxy_tool_filewatcher_FileWatcherNative_WAIT_OBJECT_0
#define wxy_tool_filewatcher_FileWatcherNative_WAIT_OBJECT_0 0L
#undef wxy_tool_filewatcher_FileWatcherNative_WAIT_TIMEOUT
#define wxy_tool_filewatcher_FileWatcherNative_WAIT_TIMEOUT 258L
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: FindFirstChangeNotification
* Signature: (Ljava/lang/String;ZI)J
*/
JNIEXPORT jlong JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindFirstChangeNotification
(JNIEnv *, jclass, jstring, jboolean, jint);
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: FindNextChangeNotification
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindNextChangeNotification
(JNIEnv *, jclass, jlong);
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: FindCloseChangeNotification
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindCloseChangeNotification
(JNIEnv *, jclass, jlong);
/*
* Class: wxy_tool_filewatcher_FileWatcherNative
* Method: WaitForSingleObject
* Signature: (JI)I
*/
JNIEXPORT jint JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_WaitForSingleObject
(JNIEnv *, jclass, jlong, jint);
#ifdef __cplusplus
}
#endif
#endif
下面是自己编写的 filewatcher.cpp
//
filewatcher.cpp : 定义 DLL 应用程序的入口点。
//
#include " stdafx.h "
#include " wxy_tool_filewatcher_FileWatcherNative.h "
#ifdef _MANAGED
#pragma managed(push, off)
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
JNIEXPORT jlong JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindFirstChangeNotification
(JNIEnv * javaEnv, jclass, jstring javaPathName, jboolean javaWatchSubtree, jint javaNotifyFilter)
{
/*
* 将java的数据类型转换过来, GetStringChars ReleaseStringChars要注意配对出现
*/
const jchar* lpJavaPathName = javaEnv->GetStringChars(javaPathName, NULL);
LPCTSTR lpPathName = (LPCTSTR) lpJavaPathName;
BOOL bWatchSubtree = (BOOL)javaWatchSubtree;
DWORD dwNotifyFilter = (DWORD)javaNotifyFilter;
HANDLE handle = FindFirstChangeNotification(lpPathName, bWatchSubtree, dwNotifyFilter);
if (handle == INVALID_HANDLE_VALUE || handle == (HANDLE)ERROR_INVALID_FUNCTION)
{
DWORD errorCode = GetLastError();
jclass exceptionClass = javaEnv->FindClass("java/lang/Exception");
javaEnv->ThrowNew(exceptionClass, "DLL Throws a Exception in FindFirstChangeNotification");
}
javaEnv->ReleaseStringChars(javaPathName, lpJavaPathName);
return (jlong)handle;
}
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindNextChangeNotification
(JNIEnv * javaEnv, jclass, jlong handle)
{
if (! FindNextChangeNotification((HANDLE) handle))
{
DWORD errorCode = GetLastError();
jclass exceptionClass = javaEnv->FindClass("java/lang/Exception");
javaEnv->ThrowNew(exceptionClass, "DLL Throws a Exception in FindNextChangeNotification");
}
}
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindCloseChangeNotification
(JNIEnv * javaEnv, jclass, jlong handle)
{
if (! FindCloseChangeNotification((HANDLE) handle))
{
DWORD errorCode = GetLastError();
jclass exceptionClass = javaEnv->FindClass("java/lang/Exception");
javaEnv->ThrowNew(exceptionClass, "DLL Throws a Exception in FindCloseChangeNotification");
}
}
JNIEXPORT jint JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_WaitForSingleObject
(JNIEnv * javaEnv , jclass, jlong hWaitHandle, jint waitTimeoutMillis)
{
return WaitForSingleObject((HANDLE) hWaitHandle, (DWORD) waitTimeoutMillis);
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
//
#include " stdafx.h "
#include " wxy_tool_filewatcher_FileWatcherNative.h "
#ifdef _MANAGED
#pragma managed(push, off)
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
JNIEXPORT jlong JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindFirstChangeNotification
(JNIEnv * javaEnv, jclass, jstring javaPathName, jboolean javaWatchSubtree, jint javaNotifyFilter)
{
/*
* 将java的数据类型转换过来, GetStringChars ReleaseStringChars要注意配对出现
*/
const jchar* lpJavaPathName = javaEnv->GetStringChars(javaPathName, NULL);
LPCTSTR lpPathName = (LPCTSTR) lpJavaPathName;
BOOL bWatchSubtree = (BOOL)javaWatchSubtree;
DWORD dwNotifyFilter = (DWORD)javaNotifyFilter;
HANDLE handle = FindFirstChangeNotification(lpPathName, bWatchSubtree, dwNotifyFilter);
if (handle == INVALID_HANDLE_VALUE || handle == (HANDLE)ERROR_INVALID_FUNCTION)
{
DWORD errorCode = GetLastError();
jclass exceptionClass = javaEnv->FindClass("java/lang/Exception");
javaEnv->ThrowNew(exceptionClass, "DLL Throws a Exception in FindFirstChangeNotification");
}
javaEnv->ReleaseStringChars(javaPathName, lpJavaPathName);
return (jlong)handle;
}
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindNextChangeNotification
(JNIEnv * javaEnv, jclass, jlong handle)
{
if (! FindNextChangeNotification((HANDLE) handle))
{
DWORD errorCode = GetLastError();
jclass exceptionClass = javaEnv->FindClass("java/lang/Exception");
javaEnv->ThrowNew(exceptionClass, "DLL Throws a Exception in FindNextChangeNotification");
}
}
JNIEXPORT void JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_FindCloseChangeNotification
(JNIEnv * javaEnv, jclass, jlong handle)
{
if (! FindCloseChangeNotification((HANDLE) handle))
{
DWORD errorCode = GetLastError();
jclass exceptionClass = javaEnv->FindClass("java/lang/Exception");
javaEnv->ThrowNew(exceptionClass, "DLL Throws a Exception in FindCloseChangeNotification");
}
}
JNIEXPORT jint JNICALL Java_wxy_tool_filewatcher_FileWatcherNative_WaitForSingleObject
(JNIEnv * javaEnv , jclass, jlong hWaitHandle, jint waitTimeoutMillis)
{
return WaitForSingleObject((HANDLE) hWaitHandle, (DWORD) waitTimeoutMillis);
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
编译生成 filewatcher.dll
可以了,我们开始做单元测试吧:
package
wxy.tool.filewatcher;
import static org.junit.Assert. * ;
import org.junit.Test;
public class FileWatcherNativeTest {
private long handle;
@Test
public void testFindFirstChangeNotification() throws Exception {
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
}
@Test
public void testFindNextChangeNotification()throws Exception{
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
FileWatcherNative.FindNextChangeNotification(handle);
}
@Test
public void testFindCloseChangeNotification() throws Exception{
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
FileWatcherNative.FindCloseChangeNotification(handle);
}
@Test
public void testWaitForSingleObject() throws Exception{
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
FileWatcherNative.FindNextChangeNotification(handle);
int returnState = FileWatcherNative.WaitForSingleObject(
handle, FileWatcherNative.INFINITE);
assertEquals(FileWatcherNative.WAIT_OBJECT_0, returnState);
}
}
import static org.junit.Assert. * ;
import org.junit.Test;
public class FileWatcherNativeTest {
private long handle;
@Test
public void testFindFirstChangeNotification() throws Exception {
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
}
@Test
public void testFindNextChangeNotification()throws Exception{
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
FileWatcherNative.FindNextChangeNotification(handle);
}
@Test
public void testFindCloseChangeNotification() throws Exception{
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
FileWatcherNative.FindCloseChangeNotification(handle);
}
@Test
public void testWaitForSingleObject() throws Exception{
handle = FileWatcherNative.FindFirstChangeNotification(
"d:/", true, 0x00000010);
FileWatcherNative.FindNextChangeNotification(handle);
int returnState = FileWatcherNative.WaitForSingleObject(
handle, FileWatcherNative.INFINITE);
assertEquals(FileWatcherNative.WAIT_OBJECT_0, returnState);
}
}
可以发现,在第一个方法那里停住了,也就是说进入了监控状态,我们在D盘下写入一个文件后,可以发现测试自动全部完成。
监控的状态如下
/** 当文件名变更 */
public static final int FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001 ;
/** 当目录名字变更 */
public static final int FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002 ;
/** 当文件属性变更 */
public static final int FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004 ;
/** 当文件大小变更 */
public static final int FILE_NOTIFY_CHANGE_SIZE = 0x00000008 ;
/** 当发现有写入数据行为 */
public static final int FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010 ;
/** 当有访问发生 */
public static final int FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020 ;
/** 当有文件创建 */
public static final int FILE_NOTIFY_CHANGE_CREATION = 0x00000040 ;
/** 当安全性发生变更 */
public static final int FILE_NOTIFY_CHANGE_SECURITY = 0x00000100 ;
/** 全部监控!! */
public static final int FILE_NOTIFY_CHANGE_ALL = 0x000000FF ;
public static final int FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001 ;
/** 当目录名字变更 */
public static final int FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002 ;
/** 当文件属性变更 */
public static final int FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004 ;
/** 当文件大小变更 */
public static final int FILE_NOTIFY_CHANGE_SIZE = 0x00000008 ;
/** 当发现有写入数据行为 */
public static final int FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010 ;
/** 当有访问发生 */
public static final int FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020 ;
/** 当有文件创建 */
public static final int FILE_NOTIFY_CHANGE_CREATION = 0x00000040 ;
/** 当安全性发生变更 */
public static final int FILE_NOTIFY_CHANGE_SECURITY = 0x00000100 ;
/** 全部监控!! */
public static final int FILE_NOTIFY_CHANGE_ALL = 0x000000FF ;