Как избежать ложных срабатываний CFileFind с расширением файла длиннее трех символов?

Когда я пытаюсь позвонить CFileFind.FindFile(_T("D://Folder//*.txt")), метод возвращает true, если единственным файлом является "foobar.txta".

Однако я не хочу, чтобы файл foobar.txta включал результат поиска. Как мне сделать это таким образом? Возможно, используя другой метод или другой, если? Я новичок в C++:))

Примечание. Эта проблема, по-видимому, не возникает, если расширение меньше 3, например, если для фильтра задано "*.tx", а для файла - "foobar.txt", метод по-прежнему (правильно) возвращает false. Кроме того, проблема, кажется, сообщается здесь, но кажется, что мне нужно заплатить, чтобы увидеть решение

4 ответа

Решение

Как отметили другие авторы, очевидная ошибка заключается в том, что файл Windows имеет псевдоним 8.3, в результате чего "foobar.txta" определяется как "foobar.txt". Чтобы убедиться, что файл, найденный CFileFind, действительно соответствует шаблону с подстановочными знаками, используйте 'PathMatchSpec', чтобы проверить файл, возвращенный функцией finder.GetNextFile(). PathMatchSpec кажется, не влияет псевдоним 8.3.

Кажется, это ошибка в CFindFile (или в Win32 API FindFirstFile). Но вы можете определить реальное расширение позже, вызвав CFindFile::GetFileName:

CFindFile finder;
BOOL bWorking = finder.FindFile(L"*.txt");

while (bWorking)
{
    bWorking = finder.FindNextFile();

    if (finder.GetFileName().Right(finder.GetFileName().ReverseFind(L'.')) != L".txt")
        // the file extension is not .txt
}

Это обычное поведение Windows для обратной совместимости. Файлы без имени "8.3" могут иметь короткий синоним. Т.е. "foobar.txta" также называется "foobar.txt", Если вы действительно имели в виду только *.txt, вам придется вручную проверить результаты. Эти результаты будут использовать длинное имя, поэтому вы можете отказаться от *.txt? файлы

Вы можете сделать ручную проверку впоследствии с PathMatchSpec("foobar.txta", "*.txt"), Обратите внимание, что, несмотря на название, эта функция действительно подходит только для сопоставления расширений. Не ожидайте ничего кроме *.ext работать.

См. Также Существует ли альтернатива Windows FindFirstFile/FindNextFile API, которая не ищет короткие имена файлов?

Я надеюсь, что это сработает.

WIN32_FIND_DATA ffd;
    CStringList strFileNameList;
    CStringList strFileMask;
    int iCntFiles = 0;
    HANDLE          hFind     = INVALID_HANDLE_VALUE;
 CONST CHAR cszFileName[] = "test.txt";

 strFileMask = strFileName.Left(strFileName.Find(cszFileName)) + "*.txt";
    hFind          = FindFirstFile(strFileMask.GetBufferSetLength(strFileMask.GetLength()), &ffd);

    if (INVALID_HANDLE_VALUE == hFind) 
    {
        return;
    } 
    else
    {
        // List all the other files in the directory.
        strFileNameList.AddTail(ffd.cFileName);
        iCntFiles++;
        while (FindNextFile(hFind, &ffd) != 0) 
        {
            strFileNameList.AddTail(ffd.cFileName);
            iCntFiles++;
        }
}

Теперь из всего текстового файла сохраните в CStringList Теперь это можно извлечь.

Другие вопросы по тегам