C ++读取添加到目录的新文件

时间:2017-11-01 20:51:11

标签: c++ file-io directory readdir dirent.h

我有一个C ++程序,在启动时,获取目录中所有文件的列表并对它们进行一些处理(将它们打包以便通过网络传输)。当前版本是静态的,程序只在程序启动时才能看到文件。现在我想把它改成一个动态版本,它可以不断看到目录中添加的新文件(让我们假设它们有一个有意义的递增名称;例如f1,f2,f3,......所以下一个将是f4这样我就可以使用一些索引了。

现在这是一段代码(静态读取所有文件):

DIR *dp;
struct dirent *dirp;
char * dir = new char[inData->dir.length() + 1];
strcpy(dir, inData->dir.c_str());
dp = opendir(dir);
int file_index = 0;
int total_files = DataUtil::count_files(dp);

if (readdir(dp) == NULL)
    rewinddir(dp);

//for each file in the directory
    while ((dirp = readdir( dp ))) {
        string f_name = dirp->d_name;
        if (f_name != "." && f_name != "..") {  // except . and ..
            //Do some processing
            my_function(f_name, file_index);
            file_index++;               
        }
    }
    closedir(dp);

我使用rewinddir(dp);函数和file_index修改了代码以注意新文件。但它不起作用。问题在哪里?

DIR *dp;
struct dirent *dirp;
char * dir = new char[inData->dir.length() + 1];
strcpy(dir, inData->dir.c_str());
dp = opendir(dir);
int file_index = 0;
int total_files = MyDataUtil::count_files(dp);

if (readdir(dp) == NULL)
    rewinddir(dp);

//for each file in the directory
    while ((dirp = readdir( dp ))) {
        string f_name = dirp->d_name;
        if (f_name != "." && f_name != "..") {
        //skip files already read
        for (int var = 0; var < file_index; var++) {
            readdir(dp);
        }
            //Do some processing
            my_function(f_name, file_index);
            file_index++;

        //reset dir stream, and update total_files
        rewinddir(dp);
        total_files = MyDataUtil::count_files(dp);            
        }
    }
    closedir(dp);

total_files函数:

int MyDataUtil::count_files(DIR *dp){
    struct dirent *dirp;
    int num = 0;

    while ((dirp = readdir( dp ))) {
        string f_name = dirp->d_name;
        if (f_name != "." && f_name != "..")
            num++;
    }
    return num;
}

以下是rewinddir文档。它说“可能会或可能不会被退回”!

Description:

The rewinddir function is used to reinitialize the directory stream dirstream, so that if you call readdir 
 it returns information about the first entry in the directory again. This function also notices if files 
 have been added or removed to the directory since it was opened with opendir. (Entries for these files 
 might or might not be returned by readdir if they were added or removed since you last called opendir 
 or rewinddir.) 

2 个答案:

答案 0 :(得分:1)

在Linux上使用inotify在您选择的目录中添加/删除/更改文件时获取异步通知 http://man7.org/linux/man-pages/man7/inotify.7.html

答案 1 :(得分:0)


这是另一种方式,也许你可以试试。

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <list>
#include <Locale.h>

using namespace std;

void ListFile(std::list<std::wstring> &list_Steady)
{
    setlocale(LC_ALL, "chs");
    WIN32_FIND_DATAW FindFileData;  
    HANDLE hFind;
    LPCWSTR s = L"C:\\Test_Monitor\\*.*";//The path of Directory you want to Monitor

    hFind = FindFirstFileW(s, &FindFileData);

    if (hFind == INVALID_HANDLE_VALUE)
    {  
        printf ("FindFirstFile failed (%d)\n", GetLastError());
        return ;
    }  
    else  
    {  
        wcout << "The first file found is " << FindFileData.cFileName << endl;
        list_Steady.push_back(FindFileData.cFileName);
    }  

    while(FindNextFile(hFind, &FindFileData))
    {
        wcout << "The next file found is " << FindFileData.cFileName << endl;
        list_Steady.push_back(FindFileData.cFileName);
    }

    FindClose(hFind);
    hFind = NULL;
}

void CompareFile(std::list<std::wstring> &new_list , std::list<std::wstring> &steady_list)
{
    bool bFound = false;

        for (std::list<std::wstring>::iterator it = new_list.begin(); it != new_list.end(); ++it)
        {
            bFound = false;
            for (std::list<std::wstring>::iterator steady_it = steady_list.begin(); steady_it != steady_list.end(); ++steady_it)
            {
                //Compare to origin list, if file still exist will return true
                if(it->compare(steady_it->c_str()) == 0)
                {
                    bFound = true;

                }
            }       

            //else this is a new file
            if(!bFound)
            {
                wcout << it->c_str() << L" new file detected" << endl;
            }           
        }

    bool bfound2 = false;

        for (std::list<std::wstring>::iterator it = steady_list.begin(); it != steady_list.end(); ++it)
        {
            bfound2 = false;
            for (std::list<std::wstring>::iterator new_it = new_list.begin(); new_it != new_list.end(); ++new_it)
            {
                //Compare to origin list, if file still exist will return true
                if(it->compare(new_it->c_str()) == 0)
                {
                    bfound2 = true;
                }
            }

            //else this file has been deleted
            if(!bfound2)
            {
                wcout<< it->c_str() << L" This file has disappeared" << endl;

            }
        }
}


int _tmain(int argc, _TCHAR* argv[])
{
    list<wstring> Steady_Directory;
    list<wstring> New_Directory;
    DWORD WaitStatus = 0;

    Steady_Directory.clear(); New_Directory.clear(); //be sure that list is clean
    ListFile(Steady_Directory);
    HANDLE FileChange = INVALID_HANDLE_VALUE;
    FileChange = ::FindFirstChangeNotification(L"C:\\Test_Monitor",FALSE,FILE_NOTIFY_CHANGE_FILE_NAME);

    if(FileChange == INVALID_HANDLE_VALUE)
    {
        cout << "LOG : FAIL to get File Change, With error code: " << ::GetLastError() << endl;
        return -1;
    }

    WaitStatus = ::WaitForSingleObject(FileChange, INFINITE);
    if (WaitStatus == WAIT_OBJECT_0)
    {
        ListFile(New_Directory);
        CompareFile(New_Directory, Steady_Directory);
    }

    system("PAUSE");
    return 0;
}

我使用两个列表,一个代表旧状态,另一个代表下一个状态,并使用 :: FindFirstChangeNotification 来订阅特定目录的状态。
目录中的任何文件更改都将设置HANDLE Filechange,然后调用函数CompareFile以确保添加或删除了哪个文件。
你可以创建一个for / while循环来使这个监视器不断工作