मैं एक सी ++ कंसोल एप्लिकेशन विकसित कर रहा हूं जिसे विंडोज ओएस पर फाइलों का प्रबंधन करना है। मुझे फ़ाइल नामों की एक 'सूची' प्राप्त करने की आवश्यकता है जिसमें एक विशिष्ट एक्सटेंशन है। मुझे बहुत सारे समाधान मिल गए हैं, सबसे अधिक सुझाया गया समाधान निम्नलिखित है:

HANDLE hFind;
WIN32_FIND_DATA data;

hFind = FindFirstFile("C:\\PWS\\*.sda", &data);
if (hFind != INVALID_HANDLE_VALUE) {
    do {
        cout << data.cFileName << endl;

    } while (FindNextFile(hFind, &data));
    FindClose(hFind);
}

मान लीजिए मेरे पास ये फ़ाइलें C:\\PWS फ़ोल्डर के अंदर हैं:

  • f001.sdac
  • f002.sda
  • f003.sdab
  • f004.sda

उपरोक्त कोड उन सभी को प्रिंट करता है, जबकि मुझे केवल f002.sda और f004.sda की आवश्यकता है।

कोई संकेत?

NB: मैं बूस्ट लाइब्रेरी का उपयोग नहीं करना चाहता।

3
baru 5 जुलाई 2017, 11:34

3 जवाब

सबसे बढ़िया उत्तर

मैंने जो समाधान अपनाया वह निम्नलिखित है:

void GetFilesByNameRootAndExtension(const string& dirPath, const string& nameRoot, string& ext, vector<string>& files)
{
    files.clear();

    stringstream ss;
    ss << dirPath << "\\" << nameRoot << "*" << ext;
    string searchKeyS = ss.str();
    const char* searchKey = searchKeyS.c_str();

    WIN32_FIND_DATA data;
    HANDLE hFind = FindFirstFile(searchKey, &data);

    ext = ext.erase(0, 1);
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            string fN = data.cFileName;
            if (fN.substr(fN.find_last_of(".") + 1) == ext) // filtering by extension
                files.push_back(fN);
        } while (FindNextFile(hFind, &data));
        FindClose(hFind);
    }
}

आपके संकेतों के लिए सभी को धन्यवाद!

0
baru 14 जुलाई 2017, 17:35

कोड "f001.sdac" और "f003.sdab" भी ढूंढता है क्योंकि FindFirstFile() और FindFirstFileEx() छोटे (8.3) और लंबे फ़ाइल नामों से मेल खाते हैं। उदाहरण के लिए, "f001.sdac" के लिए संक्षिप्त फ़ाइल नाम "f~1.sda" जैसा कुछ हो सकता है।

इसका कारण है 16-बिट के साथ पश्चगामी संगतता (आहें!) कार्यक्रम.

इस समस्या को हल करने के लिए, सभी फाइलों से मेल खाने के लिए * वाइल्डकार्ड के साथ FindFirstFile() को कॉल करें और फिर अपनी खुद की फ़िल्टरिंग करें, उदाहरण के लिए PathMatchSpec() फ़ंक्शन। PathMatchSpec() केवल स्ट्रिंग मिलान करता है इसलिए इसमें FindFirstFile() का अजीब व्यवहार नहीं है।

WIN32_FIND_DATAW data;    
HANDLE hFind = FindFirstFileW( L"C:\\PWS\\*", &data );
if( hFind != INVALID_HANDLE_VALUE ) 
{
    do 
    {
        if( ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 && 
            PathMatchSpecW( data.cFileName, L"*.sda" ) )
        {
            std::wcout << data.cFileName << std::endl;
        }
    } 
    while( FindNextFileW( hFind, &data ) );

    FindClose( hFind );
}

साइड नोट: fInfoLevelId पैरामीटर के लिए FindExInfoBasic के मान के साथ FindFirstFileEx() को कॉल करना, जो माना जाता है कि "संक्षिप्त फ़ाइल नाम को क्वेरी नहीं करता", इस समस्या के लिए मान्य समाधान नहीं है क्योंकि यह अभी भी छोटे (8.3) फ़ाइल नामों से मेल खाएगा।

2
zett42 5 जुलाई 2017, 21:51

ऐसा कुछ आपके लिए परिणामों को फ़िल्टर करना चाहिए:

bool hasFileExtension(TCHAR cFileName[], TCHAR* ptcExtension)
{
    bool result = true;
    int iFileNameLength = _tcslen(cFileName);
    int iExtensionLength = _tcslen(ptcExtension);

    if (iFileNameLength >= iExtensionLength)
    {
        for (int i = 1; i < iExtensionLength + 1 && result; i++)
        {
            if (cFileName[iFileNameLength - i] != ptcExtension[iExtensionLength - i])
            {
                result = false;
            }
        }
    }
    else
    {
        result = false;
    }

    return result;
}

void listFilesWithExtension(LPCTSTR lpFileName, TCHAR* ptcExtension)
{
    HANDLE hFind;
    WIN32_FIND_DATA data;

    hFind = FindFirstFile(lpFileName, &data);
    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (hasFileExtension(data.cFileName, ptcExtension))
            {
                wcout << data.cFileName << endl;
            }
        } while (FindNextFile(hFind, &data));
        FindClose(hFind);
    }
}

int main()
{
    LPCTSTR lpFileName = L"C:\\PWS\\*.sda";
    TCHAR* ptcExtension = _T(".sda");
    listFilesWithExtension(lpFileName, ptcExtension);
    Sleep(5000);
    return 0;
}
0
David 5 जुलाई 2017, 14:09