zoukankan      html  css  js  c++  java
  • windows下检測文件改变

            这个主要是应用在我前一篇博客里提到的脚本热载入功能。

    主要实现的功能检測目录内文件的变化(改变、新增、删除、重命名),当发现改变的时候通知lua又一次载入脚本。基本上就是一个windows api的使用。实际应用中会有一些细节须要注意,比方我习惯使用sublime text编辑。而sublime text保存文件不是直接改变文件内容,而是新增一个文件。这些细节情况须要实际使用中微调。

            代码例如以下:

    #include "FileWatcher.h"
    #include "cocos2d.h"
    #include "CCLuaEngine.h"
    
    using namespace cocos2d;
    
    #ifdef WIN32
    //  函数: WatchChanges(LPVOID lpParameter)  
    //  
    //  目的: 监控文件夹的程序  
    //  
    //  凝视:主函数创建线程时制定了这个函数的入口  
    //       届时该子程序将自己主动启动运行。  
    //  备注:由于代码不全,看以下的代码时,主要參考红色的字体部分  
    static int lastChangeTime = 0;
    
    void reloadGame()
    {
    	int time = GetTickCount();
    	if (time - lastChangeTime <= 1000) {
    		// 忽略短时间内的又一次载入请求
    		return;
    	}
    
    	Director::getInstance()->getScheduler()->performFunctionInCocosThread([](){
    		auto engine = LuaEngine::getInstance();
    		ScriptEngineManager::getInstance()->setScriptEngine(engine);
    		lua_State* L = engine->getLuaStack()->getLuaState();
    		lua_getglobal(L, "reloadGame");
    		lua_call(L, 0, 0);
    	});
    }
    DWORD WINAPI WatchChanges(LPVOID lpParameter)//返回版本号信息  
    {
    	wchar_t watchDirectory[512] = {0};
    	MultiByteToWideChar(CP_ACP, 0, (char*)lpParameter, strlen((char*)lpParameter), watchDirectory, sizeof(watchDirectory) / sizeof(wchar_t));
    
    	//创建一个文件夹句柄  
    	HANDLE handle_directory=CreateFile(watchDirectory,  
    		FILE_LIST_DIRECTORY,  
    		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,  
    		NULL,  
    		OPEN_EXISTING,  
    		FILE_FLAG_BACKUP_SEMANTICS,  
    		NULL);
    
    	if(handle_directory==INVALID_HANDLE_VALUE) {  
    		DWORD ERROR_DIR=GetLastError();
    		CCLOG("Open Directory Error");
    	}  
    
    	BOOL watch_state;  
    	while (TRUE)  
    	{
    		char buffer[1024] = {0};
    		DWORD bytesReturned = 0;
    		FILE_NOTIFY_INFORMATION* notify = (FILE_NOTIFY_INFORMATION*)buffer;
    		watch_state=ReadDirectoryChangesW(handle_directory,  (LPVOID)buffer,  
    			sizeof(buffer), TRUE,  
    			FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE,  
    			(LPDWORD)&bytesReturned, NULL, NULL);
    
    		int err = GetLastError();
    		if (err == ERROR_INVALID_FUNCTION || err == ERROR_NOTIFY_ENUM_DIR) {
    			return -1;
    		} 
    
    		if(watch_state != 0) {
    			DWORD length=WideCharToMultiByte(0,0,notify->FileName,-1,NULL,0,NULL,NULL);  
    			char fileName[256] = {0};
    			WideCharToMultiByte(0,0,notify->FileName,-1,fileName,length,NULL,NULL);  
    
    			//这里主要就是检測返回的信息,须要注意FILE_NOTIFY_INFORMATION结构体的定义,以便正确调用返回信息
    			if (notify->Action==FILE_ACTION_ADDED) {
    				CCLOG("file add: %s", fileName);
    				// sublime 改动文件是新增一个暂时文件,这个是兼容措施
    				reloadGame();
    			}  
    			if (notify->Action==FILE_ACTION_REMOVED) {
    				CCLOG("file delete: %s", fileName);
    			}  
    			if (notify->Action==FILE_ACTION_MODIFIED) {  
    				CCLOG("file changed: %s", fileName);
    				reloadGame();
    			}  
    
    			//对于以下两种情况。Action本身也是文件名称(可能是old_name也可能是new_name)  
    			if (notify->Action==FILE_ACTION_RENAMED_OLD_NAME) {
    				CCLOG("file rename old name: %s", fileName); 
    			}  
    			if (notify->Action==FILE_ACTION_RENAMED_NEW_NAME) {
    				CCLOG("file rename new name: %s", fileName);
    
    			}
    		}  
    		Sleep(500);  
    	}  
    	return 0;  
    }
    #endif
    
    void startWatch(const char* path)
    {
    #ifdef WIN32
    	static std::string s_path = path;
    	//创建一个线程专门用于监控文件变化  
    	HANDLE TrheadWatch=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WatchChanges,(void*)s_path.c_str(),0,NULL);  
    	CloseHandle(TrheadWatch);
    #endif
    }

    注冊给lua的实现:

    #include "lua_cutil.h"
    //#include <conio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <string>
    
    #include "FileWatcher.h"
    
    #include <lua.h>
    #include <lauxlib.h>
    
    int lua_cutil_watch(lua_State *pL)
    {
    	std::string path = luaL_checkstring(pL, 1);
    	startWatch(path.c_str());
    	return 0;
    }
    
    int luaopen_cutil(lua_State *pL)
    {
    	// 注冊lua函数
    	luaL_Reg reg [] = {
    		{"watch",     lua_cutil_watch},
    		{NULL, NULL}
    	};
    
    	luaL_register(pL, "cutil", reg);
    	return 1;
    }
    

    lua中调用的方式:

                    local mainPath = cc.FileUtils:getInstance():fullPathForFilename('Main.lua');
                    mainPath = string.sub(mainPath, 1, string.find(mainPath, 'Main%.lua') - 1);
                    print(mainPath);
                    cutil.watch(mainPath);


  • 相关阅读:
    加入创业公司有什么利弊
    Find Minimum in Rotated Sorted Array II
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Find Minimum in Rotated Sorted Array
    Remove Duplicates from Sorted Array
    Spiral Matrix
    Spiral Matrix II
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6897439.html
Copyright © 2011-2022 走看看