Форум программистов, компьютерный форум CyberForum.ru

поиск файлов по строкам - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 14:43     поиск файлов по строкам #1
Привет всем!

Мне нужно решить следующую задачу:
Найти первый файл в каталоге папок, удовлетворяющий заданной маске и содержащий заданный текст. И отобразить его название. Кое-какой код я написал, однако в процессе выполнения вылетает ошибка EAccesVialation.

Ошибка при выполнении 89 строки: fgets(str, 255, file);

Могли бы Вы помочь разобраться в чем ошибка?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <iostream.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <conio.h>
bool   IsFile(LPCTSTR sPath);
long  GetFindList(LPCTSTR sPath, LPCTSTR sFind, LPCTSTR sText);
bool   IsStrEqualMask(LPCTSTR s, LPCTSTR sFind);
 
 
int main()
{
        char ch;
        char start_dir[MAX_PATH];
        char file_mask[MAX_PATH];
        char text_pattern[255] = { 0 };
 
        do
        {
                 cout<<"Enter directory for search:\r\n";
                 cin>>     start_dir;
 
                        cout<<"Enter mask:\r\n";
                        cin>>file_mask;
                        cout<<"Enter text to find:\r\n";
                        cin>>text_pattern;
                        
                        if(GetFindList(start_dir, file_mask, text_pattern) < 1)
                        cout<<"Files not found\r\n";
 
 
                cout<<"Retry search?\r\nY - yes N - exit\r\n";
                cin>>ch;
        }
        while(ch == 'Y' || ch == 'y');
        return 0;
}
 
 
bool IsFile(LPCTSTR sPath)
{
        bool bFile = false;
        HANDLE hFile = CreateFile
                (
                        sPath, 
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL, 
                        OPEN_EXISTING, 
                        FILE_ATTRIBUTE_NORMAL,
                        NULL
                );
        if(hFile != INVALID_HANDLE_VALUE)
        {
                CloseHandle(hFile);
                bFile = true;
        }
        return bFile;
}
 
 
long GetFindList(LPCTSTR sPath, LPCTSTR sFind, LPCTSTR sText)
{
FILE* file = NULL;
 
       char str[255]={0};
       long nFiles = 0;
        WIN32_FIND_DATA pDATA;
        strcat(strcpy(pDATA.cFileName,sPath),"*.*");
        HANDLE hFile = FindFirstFile(pDATA.cFileName,&pDATA);
        if(hFile != INVALID_HANDLE_VALUE)
        {
                do
                {
                        if(strcmp(pDATA.cFileName,".")  == 0 ||
                           strcmp(pDATA.cFileName,"..") == 0)
                           continue;
                        else
                        {
                                if(pDATA.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY)
                                if(IsStrEqualMask(pDATA.cFileName, sFind))
                                {
 
                                file = fopen("D:\1\1.txt", "r+");
 
 
        fgets(str, 255, file);
 
        if(!strstr(str,sText)){}
        else{
        cout<<"The first file containing this text is:["<<pDATA.cFileName<<"]\r\n";
                             nFiles++;
                             break;     }
                                           }
                                              }
                                                 }
 
                while(FindNextFile(hFile,&pDATA));
        }
        return nFiles;
}
 
bool IsStrEqualMask(LPCTSTR s, LPCTSTR sFind)
{
        bool bEqual = true;
        char delim[] = " \\,.*";
        char * sMask = new char[strlen(sFind) + 1];
        strcpy(sMask,sFind);
        
        char * buf = strtok(sMask,delim);
        while(buf)
        {
                if(!strstr(s,buf))
                {
                        bEqual = false;
                        break;
                }
                buf = strtok(NULL,delim);
        }
        delete [] sMask;
        return bEqual;
}

p.s. поиск в подпапках и проверка файлов, удовлетворяющих маске на содержание заданной фразы, к сожалению пока не реализованы.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.09.2011, 14:43     поиск файлов по строкам
Посмотрите здесь:

поиск файлов C++
Поиск файлов C++
Поиск по строкам C++
Поиск файлов в директории C++
C++ Поиск файлов С++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
20.09.2011, 14:51     поиск файлов по строкам #2
На самом деле ошибка здесь:
C++
1
file = fopen("D:\1\1.txt", "r+");
символ слэш означает экранирование, видишь даже как еденицы подсвечены. Чтоб ввести символ слеш нужно его экранировать опять таки слешем, т.е. вот так:
C++
1
file = fopen("D:\\1\\1.txt", "r+");
теперь видишь как подсвечено?

Добавлено через 2 минуты
т.е. получается, что файл не открылся, из за этого и ошибка при чтении. Поэтому проверяй файл перед чтением/записью
C++
1
2
3
 file = fopen("D:\\1\\1.txt", "r+");
 if(file)
      fgets(str, 255, file);
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 15:07  [ТС]     поиск файлов по строкам #3
Kastaneda
Действительно, спасибо большое за быстрый ответ.

Надо было сразу делать автоматически перебор, а не к конкретному файлу обращаться.


Теперь задача корректно соединить sPath и pDATA.cFileName и применить эту строку в fopen().
Не подскажите как?
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
20.09.2011, 15:16     поиск файлов по строкам #4
Цитата Сообщение от lizard Посмотреть сообщение
Теперь задача корректно соединить sPath и pDATA.cFileName и применить эту строку в fopen().
Как я понял нужно к строке, хранящейся в sPath, присоеденить строку из pDATA.FileName. Тогда так
C++
1
strcat(pPath, pDATA.FileName);
при этом размер pPath должен быть достаточным, чтобы вместить pPath+pDATA.FileName. Если нет, то можно завести дополнительный массив для этого:
C++
1
2
3
4
char pPath_and_FileName[512];//размер с запасом
strcpy(pPath_and_FileName, pPath);
strcat(pPath_and_FeliName, pDATA.FileName);
file=fopen(pPath_and_FileName, "r+");
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 15:39  [ТС]     поиск файлов по строкам #5
во втором случае показывает следующую ошибку:

[C++ Error] Unit1.cpp(85): E2316 'FileName' is not a member of '_WIN32_FIND_DATAA'
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
20.09.2011, 15:43     поиск файлов по строкам #6
это я у тебя не внимательно списал, а ты не проверил
правильно будет pDATA.cFileName
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 16:32     поиск файлов по строкам #7
Цитата Сообщение от lizard Посмотреть сообщение
Могли бы Вы помочь разобраться в чем ошибка?
- у меня спросить
Поиск файла по шаблону

Цитата Сообщение от lizard Посмотреть сообщение
file = fopen("D:\1\1.txt", "r+");
fgets(str, 255, file);
- накой было код переводить
Список полей WIN32_FIND_DATA
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct _WIN32_FIND_DATAA {
    DWORD dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    DWORD nFileSizeHigh;
    DWORD nFileSizeLow;
    DWORD dwReserved0;
    DWORD dwReserved1;
    CHAR   cFileName[ MAX_PATH ];
    CHAR   cAlternateFileName[ 14 ];
#ifdef _MAC
    DWORD dwFileType;
    DWORD dwCreatorType;
    WORD  wFinderFlags;
#endif
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
Добавлено через 5 минут
lizard, есть цикл поиска, нужен первый файл удовлетворяющий маске так введи break и strcmp код топика ужастен
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 16:41  [ТС]     поиск файлов по строкам #8
да уж. тупанул я)

если все до конца исправить, применительно к коду в перовом посте, то вот так будет

C++
1
2
3
4
char sPath_and_FileName[512];
strcpy(sPath_and_FileName, sPath);
strcat(sPath_and_FileName, pDATA.cFileName);
file=fopen(sPath_and_FileName, "r+");


спасибо еще раз (:

Добавлено через 6 минут
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
есть цикл поиска, нужен первый файл удовлетворяющий маске так введи break
так он и был. строка 95.

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
strcmp код топика ужастен
можно подробнее объяснить?
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 16:47     поиск файлов по строкам #9
lizard, сейчас перепишу, верней восстановлю код + введу рекурсию чтобы все подкаталоги обрабатывал
Цитата Сообщение от lizard Посмотреть сообщение
можно подробнее объяснить?
Цитата Сообщение от lizard Посмотреть сообщение
GetFindList
- это уже готовая функция поиска, какой ещё константный путь в ней пробивать???
Цитата Сообщение от Kastaneda Посмотреть сообщение
file = fopen("D:\\1\\1.txt", "r+");
Ты файл ишещь или открываешь уже наперёд известный?

Добавлено через 1 минуту
Вобщем реализовываю задание - вбиваем каталог и выполняем в нём поиск первого файла удовлетворяющего маске, скоро отпишусь...(как я ShlDialog выбора каталога напугал и будем его руками вводить)
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 16:56  [ТС]     поиск файлов по строкам #10
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Ты файл ишещь или открываешь уже наперёд известный?
да ясное дело что ищем. Я просто отладку делал с реакцией на найденное слово в файле, поэтому ввел адрес на время
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 17:24     поиск файлов по строкам #11
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Вобщем реализовываю задание - вбиваем каталог и выполняем в нём поиск первого файла удовлетворяющего маске
Вот Си код (SHL-диалог выбора файла не убирал, т.к достаёт вручную вбивать пути на своём компьютере, если есть желание его убрать - убираем, у меня этого желания нет)
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream.h>//i/o
#include <windows.h> //FindFirst(Next)File
#include <shlobj.h>  //Диалог выбора файла
#include <stdio.h>   //sprintf
//Руссификация
ostream& operator<<(ostream &stream,char* s){
    for(char* ps=s; *ps; ps++){
        if(*ps=='ё')
            stream<<char(241);
        else if(*ps=='Ё')
            stream<<char(240);
        else if(*ps>=-64 && *ps<=-17)           
            stream<<char(*ps+64+128);
        else if(*ps<0)
            stream<<char(*ps+64+176);
        else
            stream<<*ps;
    }
    return stream;
}
 
char * SelectFile(HWND hWnd);
bool   IsFile(LPCTSTR sPath);
bool   FindFile(LPCTSTR sPath, LPCTSTR sFind);
bool   IsStrEqualMask(LPCTSTR s, LPCTSTR sFind);
 
int main()
{
    char ch;
    char szFilePath[MAX_PATH];
    char szFindMask[MAX_PATH];
    HWND hWnd = GetForegroundWindow();//Находим дескриптор окна консоли
    do
    {
        if(!strcpy(szFilePath,SelectFile(hWnd)))
            cout<<"Файл не выбран";
        else
        {
            if(IsFile(szFilePath))
            {
                    cout<<"Выбран файл\r\n";
                    szFilePath[strlen(szFilePath) - strlen(strrchr(szFilePath,'\\')) + 1] = '\0'; 
            }
            cout<<"Каталог для поиска:\r\n["<<szFilePath<<"]\r\n";
            cout<<"Введите маску поиска\r\n";
            cin>>szFindMask;
            if(!FindFile(szFilePath, szFindMask))
                cout<<"Поиск не дал результатов\r\n";
        }
        cout<<"Y - Повторить поиск\r\n";
        cin>>ch;
    }
    while(ch == 'Y' || ch == 'y');
    return 0;
}
 
char * SelectFile(HWND hWnd)
{
    ShowWindow(hWnd,SW_HIDE);
    char sPath[MAX_PATH];sPath[0] = '\0';
    LPCITEMIDLIST lpItemDList;
    BROWSEINFO bi = {NULL, NULL, sPath,
       "Выберите файл или каталог",
        BIF_DONTGOBELOWDOMAIN|BIF_BROWSEINCLUDEFILES,
        NULL,
        NULL,
        0
    };
    if((lpItemDList = SHBrowseForFolder(&bi)))
    {
        if(SHGetPathFromIDList(lpItemDList, sPath))
            GetShortPathName((LPCTSTR)sPath,sPath,strlen(sPath));
    }
    ShowWindow(hWnd,SW_SHOW);
    return &sPath[0];
}
 
bool IsFile(LPCTSTR sPath)
{
    bool bFile = false;
    HANDLE hFile = CreateFile
        (
            sPath, 
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL, 
            OPEN_EXISTING, 
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );
    if(hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        bFile = true;
    }       
    return bFile;
}
 
 
bool FindFile(LPCTSTR sPath, LPCTSTR sFind)
{
    bool bFind = false;
    char sDir[MAX_PATH];
    WIN32_FIND_DATA pDATA;
    strcat(strcpy(pDATA.cFileName,sPath),"\\*.*");
    HANDLE hFile = FindFirstFile(pDATA.cFileName,&pDATA);
    if(hFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            if(strcmp(pDATA.cFileName,".")  == 0 ||
               strcmp(pDATA.cFileName,"..") == 0)
               continue;
            else
            {
                if(pDATA.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY)
                if(IsStrEqualMask(pDATA.cFileName, sFind))
                {
                    cout<<"Найден файл :["<<pDATA.cFileName<<"]\r\n";
                    bFind = true;
                    break;
                }
                else
                {
                    //Нашли подкаталог - ныряем в него
                    sprintf(sDir,"%s\\%s",sPath, pDATA.cFileName);
                    if((bFind = FindFile(sDir, sFind)))
                        break;//Если поиск успешен, сразу прекращаем поиск
                }
            }
        }
        while(FindNextFile(hFile,&pDATA));
    }
    return bFind;
}
 
bool IsStrEqualMask(LPCTSTR s, LPCTSTR sFind)
{
    bool bEqual = true;
    //шаблон может содержать ' ' '\\' ',' '.' '*'
    char delim[] = " \\,.*";
    char * sMask = new char[strlen(sFind) + 1];
    strcpy(sMask,sFind);
    
    char * buf = strtok(sMask,delim);
    while(buf)
    {
        if(!strstr(s,buf))
        {
            bEqual = false;
            break;
        }
        buf = strtok(NULL,delim);
    }
    delete [] sMask;
    return bEqual;
}
[Результат работы]
Каталог для поиска:
[D:\МОИДОК~1\0292~1\21EF~1]
Введите маску поиска
*.xls
Найден файл :[Общий баланс(сентябрь)-2011.xls]
Y - Повторить поиск


Добавлено через 1 минуту
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
if(IsStrEqualMask(pDATA.cFileName, sFind))
* * * * * * * * * * * * * * * * {
* * * * * * * * * * * * * * * * * * * * cout<<"Найден файл :["<<pDATA.cFileName<<"]\r\n";
* * * * * * * * * * * * * * * * * * * * bFind = true;
* * * * * * * * * * * * * * * * * * * * break;
* * * * * * * * * * * * * * * * }
* * * * * * * * * * * * * * * * else
* * * * * * * * * * * * * * * * {
* * * * * * * * * * * * * * * * * * * * //Нашли подкаталог - ныряем в него
* * * * * * * * * * * * * * * * * * * * sprintf(sDir,"%s\\%s",sPath, pDATA.cFileName);
* * * * * * * * * * * * * * * * * * * * if((bFind = FindFile(sDir, sFind)))
* * * * * * * * * * * * * * * * * * * * * * * * break;//Если поиск успешен, сразу прекращаем поиск
* * * * * * * * * * * * * * * * }
if((bFind = FindFile(sDir, sFind))) - рекурсивный обход всех подкаталогов

Добавлено через 10 минут
Вот код аналогичной функциональности позволяющий исключить ShlDialog
C
1
2
3
4
5
6
7
8
9
szFilePath[0] = '\0';
        cout<<"Введите каталог\r\n";
        cin.getline(szFilePath,MAX_PATH);
        if(szFilePath[0] == '\0')
            cout<<"Файл не выбран\r\n";
        else
        {
            if(IsFile(szFilePath))
            {
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
20.09.2011, 17:30     поиск файлов по строкам #12
lizard, если пишешь на С++, то логичней вместо char* использовать для строк класс string
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 17:31  [ТС]     поиск файлов по строкам #13
за рекурсию спасибо.
Но в задании цель не вывести название первого файла удовлетворяющего маске, а вывести название первого файла удовлетворяющего маске и в содержащего заданную слово\фразу. Поэтому и входящий параметр добавился в функцию. И поэтому же там появились строки

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
 
char sPath_and_FileName[512];
strcpy(sPath_and_FileName, sPath);
strcat(sPath_and_FileName, pDATA.cFileName);
file=fopen(sPath_and_FileName, "r+");
fgets(str, 255, file);
 
        if(!strstr(str,sText)){}
        else{
        cout<<"The first file containing this text is:["<<pDATA.cFileName<<"]\r\n";
                             nFiles++;
                             break;     }
...
Nameless One
Эксперт С++
 Аватар для Nameless One
5753 / 3402 / 255
Регистрация: 08.02.2010
Сообщений: 7,393
20.09.2011, 17:35     поиск файлов по строкам #14
Кстати, по теме, глянь исходники find
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 18:32     поиск файлов по строкам #15
Цитата Сообщение от lizard Посмотреть сообщение
file=fopen(sPath_and_FileName, "r+");
fgets(str, 255, file);
if(!strstr(str,sText)){}
* * * * else{
- в функцию нужно передавать текст для поиска, а не открывать файл, сейчас подправлю, если честно задание сложно было понять...
lizard
 Аватар для lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 18:53  [ТС]     поиск файлов по строкам #16
Так текст нужно и передавать (что уже реализовано) и считывать из файлов - что бы найти искомое в них. Ну это насколько я понимаю алгоритм.


Может быть просто я не оч понятно описал.

1) функция(директория поиска, маска, искомый текст)

выводит на экран первый подходящий файл.


по большому счету в этой теме уже есть весь необходимый код, надо только соединить все в 1 программу
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.09.2011, 19:10     поиск файлов по строкам
Еще ссылки по теме:

C++ Поиск файлов
Поиск тестовых файлов C++
Поиск файлов по расширению C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 19:10     поиск файлов по строкам #17
Вот подправил
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include <iostream.h>//i/o
#include <windows.h> //FindFirst(Next)File
#include <shlobj.h>  //Диалог выбора файла
#include <stdio.h>   //sprintf
//Руссификация
ostream& operator<<(ostream &stream,char* s){
        for(char* ps=s; *ps; ps++){
                if(*ps=='ё')
                        stream<<char(241);
                else if(*ps=='Ё')
                        stream<<char(240);
                else if(*ps>=-64 && *ps<=-17)                   
                        stream<<char(*ps+64+128);
                else if(*ps<0)
                        stream<<char(*ps+64+176);
                else
                        stream<<*ps;
        }
        return stream;
}
 
char * SelectFile(HWND hWnd);
bool   IsFile(LPCTSTR sPath);
//Поиск файла в каталоге sPath по маске sMask и наличии текста sFind в нём
bool   FindFile(LPCTSTR sPath, LPCTSTR sMask, LPCTSTR sFind);
//Поиск текста sFind в файле sPath
bool   FindText(LPCTSTR sPath, LPCTSTR sFind);
bool   IsStrEqualMask(LPCTSTR s, LPCTSTR sFind);
 
int main()
{
    char ch;
    char szFilePath[MAX_PATH];
    char szFindMask[MAX_PATH];
    char szFindText[1024];//Для вводе текста для поиска есть хоть каки*то ограничения
    HWND hWnd = GetForegroundWindow();//Находим дескриптор окна консоли
    do
    {
        if(!strcpy(szFilePath,SelectFile(hWnd)))
            cout<<"Файл не выбран\r\n";
        else
        {
            if(IsFile(szFilePath))
            {
                cout<<"Выбран файл\r\n";
                szFilePath[strlen(szFilePath) - strlen(strrchr(szFilePath,'\\')) + 1] = '\0'; 
            }
            cout<<"Каталог для поиска:\r\n["<<szFilePath<<"]\r\n";
            cout<<"Введите маску поиска\r\n";
            cin.getline(szFindMask,MAX_PATH);
            cout<<"Введите текст поиска\r\n";
            cin.getline(szFindText,1024);
            if(!FindFile(szFilePath, szFindMask, szFindText))
                cout<<"Поиск не дал результатов\r\n";
        }
        cout<<"Y - Повторить поиск\r\n";
        cin>>ch;
    }
    while(ch == 'Y' || ch == 'y');
    return 0;
}
 
char * SelectFile(HWND hWnd)
{
    ShowWindow(hWnd,SW_HIDE);
    char sPath[MAX_PATH];sPath[0] = '\0';
    LPCITEMIDLIST lpItemDList;
    BROWSEINFO bi = 
    {
        NULL, 
        NULL, 
        sPath,
        "Выберите файл или каталог",
        BIF_DONTGOBELOWDOMAIN|BIF_BROWSEINCLUDEFILES,
        NULL,
        NULL,
        0
    };
    if((lpItemDList = SHBrowseForFolder(&bi)))
    {
        if(SHGetPathFromIDList(lpItemDList, sPath))
            GetShortPathName((LPCTSTR)sPath,sPath,strlen(sPath));
    }
    ShowWindow(hWnd,SW_SHOW);
    return &sPath[0];
}
 
bool IsFile(LPCTSTR sPath)
{
    bool bFile = false;
    HANDLE hFile = CreateFile
        (
            sPath, 
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL, 
            OPEN_EXISTING, 
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );
     if(hFile != INVALID_HANDLE_VALUE)
     {
         CloseHandle(hFile);
         bFile = true;
     }               
     return bFile;
}
 
 
bool FindFile(LPCTSTR sPath, LPCTSTR sMask, LPCTSTR sFind)
{
    bool bFind = false;
    char sDir[MAX_PATH];
    WIN32_FIND_DATA pDATA;
    strcat(strcpy(pDATA.cFileName,sPath),"\\*.*");
    HANDLE hFile = FindFirstFile(pDATA.cFileName,&pDATA);
    if(hFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            if(strcmp(pDATA.cFileName,".")  == 0 ||
               strcmp(pDATA.cFileName,"..") == 0)
               continue;
            else
            {
                sprintf(sDir,"%s\\%s",sPath, pDATA.cFileName);
                if(pDATA.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY)
                {
                    if(IsStrEqualMask(pDATA.cFileName, sMask))
                    if(FindText(sDir, sFind))
                    {
                        cout<<"Найден файл :["<<sDir<<"]\r\n";
                        bFind = true;
                        //break;//Если поиск успешен, сразу прекращаем поиск
                    }
                }
                else
                {
                    //Нашли подкаталог - ныряем в него
                    if((bFind = FindFile(sDir, sMask, sFind)))
                    {
                        //break;//Если поиск успешен, сразу прекращаем поиск
                    }
                }
            }
        }
        while(FindNextFile(hFile,&pDATA));
    }
    return bFind;
}
 
bool FindText(LPCTSTR sPath, LPCTSTR sFind)
{
    long sLen;
    char * str;
    bool bRet = false;
    FILE * f = fopen(sPath,"r");
    if(f)
    {
        fseek(f,0,SEEK_END);
        sLen = ftell(f);
        fseek(f,0,SEEK_SET);
        if((str = new char[sLen + 1]))
        {
            fread(str,sLen,1,f);
            str[sLen] = '\0';
        }
        fclose(f);
        if(str)
        {
            //Решил не изобретать велосипед а воспользуваться уже имеющейся функцией
            bRet = IsStrEqualMask(str, sFind);
            delete [] str;
        }
    }
    return bRet;
}
 
bool IsStrEqualMask(LPCTSTR s, LPCTSTR sFind)
{
    bool bEqual = true;
    //шаблон может содержать ' ' '\\' ',' '.' '*'
    char delim[] = " \\,.*";
    char * sMask = new char[strlen(sFind) + 1];
    strcpy(sMask,sFind);
        
    char * buf = strtok(sMask,delim);
    while(buf)
    {
        if(!strstr(s,buf))
        {
            bEqual = false;
            break;
        }
        buf = strtok(NULL,delim);
     }
     delete [] sMask;
     return bEqual;
}
Проверял работу на файле который прикладываю (скопировал в 2 подкаталога). Поиск длиться какое то премя, но всё отработало норм
[Результат работы]
Каталог для поиска:
[D:\MICROS~1]
Введите маску поиска
~Test*.txt
Введите текст поиска
TEST
Найден файл :[D:\MICROS~1\CyberForum\SearchMaskText\~TestFile~.txt]
Найден файл :[D:\MICROS~1\CyberForum\~TestFile~.txt]
Поиск не дал результатов
Y - Повторить поиск

PS:Чтобы убить Program idle (потря программой фокуса на окно, можно ввести функцию которую привожу ниже), вставляем её в цикл

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void PumpMessages(HWND hWnd)
{
    ASSERT(hWnd!=NULL);
    MSG msg;
    // Handle dialog messages
    while(PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
    {
        if(!IsDialogMessage(hWnd,&msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);  
        }
    }
}
Yandex
Объявления
20.09.2011, 19:10     поиск файлов по строкам
Ответ Создать тему
Опции темы

Текущее время: 03:17. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru