首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CreateFile,ReadDirectoryChanges问题

CreateFile,ReadDirectoryChanges问题
EN

Stack Overflow用户
提问于 2012-10-25 15:33:21
回答 1查看 1.8K关注 0票数 1

我正在使用ReadDirectoryChangesW监视我用CreateFile打开的文件夹,一旦添加了一个文件,我调用一个函数(OnFileChanged)来读取大小并打开它进行读取,我的应用程序对于小文件运行良好,但当我尝试将一个大文件复制到我的文件夹(7,24M)时出现问题,并且我在调用fopen读取它后得到Permission denied错误。

观看过程基于this

代码语言:javascript
复制
    void Init(const QString FullPath)
    {    ...
         hDir = CreateFile(
                dirPath, // pointer to the directory containing the tex files
                FILE_LIST_DIRECTORY|GENERIC_READ,                // access (read-write) mode
                FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,  // share mode
                NULL, // security descriptor
                OPEN_EXISTING, // how to create
                FILE_FLAG_BACKUP_SEMANTICS  | FILE_FLAG_OVERLAPPED , // file attributes
                NULL); // file with attributes to copy


            SecureZeroMemory (&overl, sizeof(overl));
            SecureZeroMemory(buffer, sizeof(buffer));
            overl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

            // watch the directory
           BOOL res= ReadDirectoryChangesW(
                 hDir, /* handle to directory */
                 &buffer[curBuffer], /* read results buffer */
                 sizeof(buffer[curBuffer]), /* length of buffer */
                 FALSE, /* monitoring option */
                 FILE_NOTIFY_CHANGE_FILE_NAME ,
                 //FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */
                 NULL, /* bytes returned */
                 &overl, /* overlapped buffer */
                 NULL); /* completion routine */

    }

void StartWatchThread()
{
    // if the thread already exists then stop it
    if (IsThreadRunning())
        SynchronousAbort();

    //CrashIf(!hDir);
    if(!hDir)
       { qDebug()<<" handle "<<hDir<<" last error"<<GetLastError();
        exit(-1);}

    else
    {// reset the hEvtStopWatching event so that it can be set if
    // some thread requires the watching thread to stop
    ResetEvent(hEvtStopWatching);

    DWORD watchingthreadID;
    qDebug()<<"befrore creating thread";
    hWatchingThread = CreateThread(NULL, 0, WatchingThread, this, 0, &watchingthreadID);
    qDebug()<<"watchingthreadID"<<watchingthreadID;
    }
}


DWORD WINAPI WatchingThread(void *param)
{
    //qDebug()<<"in WatchingThread";
    FileWatcher *fw = (FileWatcher *)param;

    HANDLE hp[2] = { fw->hEvtStopWatching, fw->overl.hEvent };
    for (;;)
    {

        DWORD dwObj = WaitForMultipleObjects((sizeof(hp)/(sizeof(hp[0])))
                                             , hp, FALSE, INFINITE);
        if (dwObj == WAIT_OBJECT_0) // the user asked to quit the program
        {
            qDebug()<<"in WatchingThread the user asked to quit the program";
            //exit(-1);
            break;
        }
        if (dwObj != WAIT_OBJECT_0 + 1)
        {
            // BUG!
            //assert(0);
            qDebug()<<"dwObj "<<dwObj<<" last error "<<GetLastError();
            break;
        }
        //qDebug()<<"WatchingThread fw->NotifyChange() ";

        //if (fw->wakeup)
            fw->NotifyChange();

    }
    return 0;
} 


bool NotifyChange()
{
    //qDebug()<<"in NotifyChange";

    GetOverlappedResult(hDir, &overl, &dwNumberbytes, FALSE);

    FILE_NOTIFY_INFORMATION *pFileNotify = (FILE_NOTIFY_INFORMATION *)buffer[curBuffer];
    // Switch the 2 buffers
    curBuffer = (curBuffer + 1) % (sizeof(buffer)/(sizeof(buffer[0])));
    SecureZeroMemory(buffer[curBuffer], sizeof(buffer[curBuffer]));
    // start a new asynchronous call to ReadDirectory in the alternate buffer
    ReadDirectoryChangesW(
         hDir, /* handle to directory */
         &buffer[curBuffer], /* read results buffer */
         sizeof(buffer[curBuffer]), /* length of buffer */
         FALSE, /* monitoring option */
         FILE_NOTIFY_CHANGE_FILE_NAME  ,
         //FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */
         NULL, /* bytes returned */
        &overl, /* overlapped buffer */
         NULL); /* completion routine */

    // Note: the ReadDirectoryChangesW API fills the buffer with WCHAR strings.
    for (;;) {

        if (pFileNotify->Action == FILE_ACTION_ADDED)
        {
            qDebug()<<"in NotifyChange if ";
                char szAction[42];
                char szFilename[MAX_PATH] ;
                memset(szFilename,'\0',sizeof( szFilename));
                strcpy(szAction,"added");
                wcstombs( szFilename, pFileNotify->FileName, MAX_PATH);

                OnFileChanged(szFilename,szAction);
                qDebug()<<"in NotifyChange after OnFileChanged ";

        }

        // step to the next entry if there is one
        if (!pFileNotify->NextEntryOffset)
            return false;
        pFileNotify = (FILE_NOTIFY_INFORMATION *)((PBYTE)pFileNotify + pFileNotify->NextEntryOffset);
    }
    pFileNotify=NULL;
    return true;
}

我不知道如何处理这个文件,所以不让我读?我试图在调用OnFileChanged之后调用睡眠(),并在它结束时唤醒,但徒劳无功。有什么想法请告诉我。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-25 16:35:06

我调用一个函数(OnFileChanged)来读取大小并将其打开以供读取

这是迟早会失败的。文件更改通知是在进程写入文件时生成的。这会阻止您在进程尚未完成写入或保持文件打开的情况下打开文件。并且不允许读共享,这在写文件的程序中很常见。这当然与文件大小有关,文件越大,写入的时间就越长,所以当其他进程还没有关闭它时,你试图打开它的可能性就越大。

你需要处理这个可能的不幸事件。除了将路径保留在队列中之外,您什么也做不了,以便稍后可以尝试。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13063710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档