一、目的
cocos2dx-lua游戏开发过程中能够监控某个文件夹下的文件变化。
二、实现window平台监控文件变化
FileWatch.h
#ifndef __FILE_WATCH_H__
#define __FILE_WATCH_H__
#include <vector>
#include <string>
#include <iostream>
#include "platform/CCPlatformConfig.h"
using namespace std;
class FileWatch
{
public:
/*
file notify struct
action // it is a flag same as FILE_NOTIFY_INFORMATION's action
old_name // old file name
new_name // it has value only when the action is FILE_ACTION_RENAMED_OLD_NAME
*/
struct FileNotify
{
int action;
std::string old_name;
std::string new_name;
};
/*
define struct for transfer params to thread
*/
struct FileWatchThreadParam
{
std::string *watch_dir; // watch_dir
std::vector<FileWatch::FileNotify> *container; // file_name vector
};
virtual ~FileWatch();
// single instance
static FileWatch *getInstance();
// create thread to monitor the dir
void createFileWatchThread(std::string watchDir);
// close monitor thread
void closeFileWatchThread();
std::vector<FileWatch::FileNotify> getChangeFileArray();
std::string getWatchDir();
protected:
FileWatch();
private:
static FileWatch *_instance;
FileWatchThreadParam _fwtp;
// all notification
std::vector<FileWatch::FileNotify> file_name;
// monitor dir
std::string watch_dir;
};
#endif // __FILE_WATCH_H__
FileWatch.cpp
#include <windows.h>
#include <tchar.h>
#include "FileWatch.h"
FileWatch *FileWatch::_instance = nullptr;
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
// monitor thread
HANDLE hThread;
LPDWORD threadId;
HANDLE dirHandle;
#endif
FileWatch::FileWatch()
{
}
FileWatch::~FileWatch()
{
if (_instance == nullptr)
return;
delete _instance;
_instance = nullptr;
}
FileWatch *FileWatch::getInstance()
{
if (!_instance)
{
_instance = new FileWatch();
}
return _instance;
}
string WString2String(wstring wstr)
{
string result;
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
char* buffer = new char[len + 1];
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, buffer, len + 1, NULL, NULL);
//buffer[len] = '\0';
result.append(buffer);
delete[] buffer;
return result;
}
LPCWSTR stringToLPCWSTR(std::string orig)
{
size_t origsize = orig.length() + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(orig.length() - 1));
mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
return wcstring;
}
void _fileWatcher(std::string *dir, vector<FileWatch::FileNotify> *fn)
{
DWORD cbBytes;
char notify[1024] = "";
dirHandle = CreateFile(stringToLPCWSTR(*dir), GENERIC_READ | GENERIC_WRITE | FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (dirHandle == INVALID_HANDLE_VALUE)
{
printf("[FileWatch] CreateFile error:" + GetLastError());
return;
}
FILE_NOTIFY_INFORMATION *pNotification = (FILE_NOTIFY_INFORMATION *)notify;
BOOL watch_state;
while (true)
{
watch_state = ReadDirectoryChangesW(dirHandle, ¬ify, 1024, true,
//FILE_NOTIFY_CHANGE_FILE_NAME
FILE_NOTIFY_CHANGE_DIR_NAME
| FILE_ACTION_RENAMED_OLD_NAME
| FILE_ACTION_RENAMED_NEW_NAME
//| FILE_NOTIFY_CHANGE_CREATION
//| FILE_NOTIFY_CHANGE_LAST_WRITE
| FILE_NOTIFY_CHANGE_SIZE,
&cbBytes, NULL, NULL);
if (watch_state == FALSE)
{
printf("[FileWatch] file watch error!");
break;
}
else if (GetLastError() == ERROR_INVALID_FUNCTION)
{
printf("[FileWatch] system not support");
break;
}
else if (GetLastError() == ERROR_NOTIFY_ENUM_DIR)
{
printf("[FileWatch] out of memory");
break;
}
else {
std::wstring szFileName = pNotification->FileName;
FileWatch::FileNotify notifyStruct;
notifyStruct.action = pNotification->Action;
notifyStruct.old_name = "";
notifyStruct.old_name = WString2String(szFileName);
if (pNotification->Action == FILE_ACTION_RENAMED_OLD_NAME) {
// get new file name
WCHAR newName[1024]