Advertisement
anticlown

Lab_7_2(search byte sequence in files in directory with threads)

Dec 2nd, 2023 (edited)
1,089
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.50 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #include <pthread.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>
  9. #include <stdbool.h>
  10. #include <sys/wait.h>
  11. #include <errno.h>
  12. #include <limits.h>
  13.  
  14. typedef struct dirent DIRENT;
  15. typedef struct stat STAT;
  16.  
  17. //cтруктура для создания потока
  18. typedef struct
  19. {
  20.     const char *fullPath;
  21.     const char *fileName;
  22.     int outputFile;
  23.     const char* stringForSearch;
  24. } ThreadArgs;
  25.  
  26. //прототипы
  27. void searchStringInFile(const char *filePath, const char *fileName, const int outputFile, const char* stringForSearch);
  28. void *threadFuncForSearch(void *args);
  29. void searchInDirectory(const char *dirToSearch, const char *stringForSearch, const int outputFile, int maxThreads, pthread_t *threadIDs, int *threadCount);
  30. void printFileStats(const int outputFile, const char *fullPath, const char *fileName, const int bytesChecked, const unsigned isFound);
  31. void printTaskInfo();
  32.  
  33.  
  34. void searchStringInFile(const char *filePath, const char *fileName, const int outputFile, const char* stringForSearch)
  35. {
  36.     FILE *fileForCheckPointer;
  37.     if ((fileForCheckPointer = fopen(filePath, "rb")) == NULL) // файл не открылся для чтения
  38.     {
  39.         fprintf(stderr, "Не удалось прочитать данные в файле %s.\n", fileName);
  40.         return;
  41.     }
  42.  
  43.     char tempChar;
  44.     int byteCounter = 0;
  45.     unsigned isFound = 0;
  46.  
  47.     while (!feof(fileForCheckPointer))
  48.     {
  49.         byteCounter++;
  50.         tempChar = getc(fileForCheckPointer);
  51.         if (tempChar == stringForSearch[0]) // если текущий выбранный символ в файле совпал с первым символом проверочной строки
  52.         {
  53.             int i = 1;
  54.             isFound = 1;
  55.             while (stringForSearch[i] != '\0' && isFound)
  56.             { // пока строка не кончается и сравниваемые символы равны
  57.                 isFound = stringForSearch[i] == getc(fileForCheckPointer);
  58.                 i++;
  59.             }
  60.         }
  61.     }
  62.     printFileStats(outputFile, filePath, fileName, byteCounter, isFound);
  63.     fclose(fileForCheckPointer);
  64. }
  65.  
  66. void *threadFuncForSearch(void *args)
  67. {
  68.     ThreadArgs *threadArgs = (ThreadArgs *)args;
  69.     const char *filePath = threadArgs->fullPath;
  70.     const char *name = threadArgs->fileName;
  71.     const int outputFile = threadArgs->outputFile;
  72.     const char* stringForSearch = threadArgs->stringForSearch;
  73.  
  74.     printf("\nID нового потока: %ld\n", pthread_self());
  75.     searchStringInFile(filePath, name, outputFile, stringForSearch);
  76.  
  77.     free(args);
  78.     return NULL;
  79. }
  80.  
  81. void searchInDirectory(const char *dirToSearch, const char *stringForSearch, const int outputFile, int maxThreads, pthread_t *threadIDs, int *threadCount)
  82. {
  83.     DIR *dir = opendir(dirToSearch);
  84.     if (dir == NULL) // если каталог не удалось открыть
  85.     {
  86.         perror("Ошибка при открытии каталога!");
  87.     }
  88.  
  89.     DIRENT *entry;
  90.     while ((entry = readdir(dir)) != NULL)
  91.     {
  92.         char fullPath[PATH_MAX];
  93.         snprintf(fullPath, PATH_MAX, "%s/%s", dirToSearch, entry->d_name);
  94.  
  95.         STAT buffer;
  96.         stat(fullPath, &buffer);
  97.  
  98.         if (S_ISREG(buffer.st_mode))
  99.         {
  100.             ThreadArgs *threadArgs = (ThreadArgs *)malloc(sizeof(ThreadArgs));
  101.             threadArgs->fullPath = strdup(fullPath);
  102.             threadArgs->fileName = strdup(entry->d_name);
  103.             threadArgs->outputFile = outputFile;
  104.             threadArgs->stringForSearch = stringForSearch;
  105.  
  106.             pthread_create(&threadIDs[*threadCount], NULL, threadFuncForSearch, (void *)threadArgs);
  107.             (*threadCount)++;
  108.  
  109.             if (*threadCount >= maxThreads)
  110.             {
  111.                 for (int i = 0; i < maxThreads; i++)
  112.                 {
  113.                     pthread_join(threadIDs[i], NULL);
  114.                 }
  115.                 *threadCount = 0;
  116.             }
  117.         }
  118.     }
  119.  
  120.     closedir(dir);
  121.  
  122.     for (int i = 0; i < *threadCount; i++)
  123.     {
  124.         pthread_join(threadIDs[i], NULL);
  125.     }
  126. }
  127.  
  128. /*      процедуры для вывода     */
  129. void printFileStats(const int outputFile, const char *fullPath, const char *fileName, const int bytesChecked, const unsigned isFound)
  130. {
  131.     printf("\n\tПуть: %s\n", fullPath);
  132.     printf("\tИмя файла: %s\n", fileName);
  133.     printf("\tКоличество просмотренных байт: %d\n", bytesChecked);
  134.     printf("\tНайдена ли строка: %s\n", ((isFound) ? "Да" : "Нет"));
  135.  
  136.     dprintf(outputFile, "\n\tПуть: %s\n", fullPath);
  137.     dprintf(outputFile, "\tИмя файла: %s\n", fileName);
  138.     dprintf(outputFile, "\tКоличество просмотренных байт: %d\n", bytesChecked);
  139.     dprintf(outputFile, "\tНайдена ли строка: %s\n\n", ((isFound) ? "Да" : "Нет"));
  140. }
  141.  
  142. void printTaskInfo()
  143. {
  144.     printf("\n\tДанная программа ищет в заданном каталоге все файлы,\n\t\t которые содержат заданную строку.\n\tРезультаты выводятся на консоль и в указанный файл.\n\n");
  145. }
  146. /*      процедуры для вывода     */
  147.  
  148. int main(int argc, char *argv[])
  149. {
  150.     const int NUM_OF_ARGS = 5;
  151.     if (argc != NUM_OF_ARGS)
  152.     {
  153.         fprintf(stderr, "Неверный ввод!\nФормат ввода: %s <заданный каталог> <строка для поиска> <файл вывода> <кол-во процессов>\n", argv[0]);
  154.         fprintf(stderr, "Повторите запуск программы!\n");
  155.         return EXIT_FAILURE;
  156.     }
  157.  
  158.     char *directoryPath = argv[1];
  159.     char *stringForSearch = argv[2];
  160.     const int outputFile = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
  161.     if (outputFile == -1)
  162.     {
  163.         perror("Ошибка при открытии файла для записи!");
  164.         return EXIT_FAILURE;
  165.     }
  166.     const int maxThreads = atoi(argv[4]);
  167.     pthread_t threadIDs[maxThreads];
  168.     int threadCount = 0;
  169.  
  170.     printTaskInfo();
  171.     searchInDirectory(directoryPath, stringForSearch, outputFile, maxThreads, threadIDs, &threadCount);
  172.     close(outputFile);
  173.     printf("\n\t\tВывод в файл успешно завершен!\n");
  174.  
  175.     return EXIT_SUCCESS;
  176. }
  177.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement