Лабораторная работа: Работа с файлами в асинхронном режиме

Цель работы

Изучение способов работы с файлами в Win32 API. Изучение асинхронного режима работы с файлами.

Список используемых системных вызовов

CreateFile, CloseHandle, ReadFile, WriteFile, CancelIo, WaitForSingleObject, WaitForMultipleObjects, GetFilePointer, SetFilePointer, FindFirstFile, FindNextFile, FindClose, SearchFile.

Методические указания

При выполнении данной лабораторной работы запрещается пользоваться группами функций Win32 API CopyFile… и MoveFile…, а также функциями библиотеки shell32.dll.
Для создания/открытия файла в Win32 API используется функция CreateFile (параметр dwCreationDisposition используется для задания режима открытия или создания файла). Чтение из файла и запись в файл реализуются с помощью функций ReadFile и WriteFile. Дескриптор файла закрывается с помощью стандартной функции CloseHandle.
Поиск файла в заданном каталоге возможен с помощью функций FindFirstFile, FindNextFile, FindClose. Поиск файла по путям поиска производится с помощью функции SearchFile.
В Win32 API реализована возможность задания асинхронного режима работы с файлами. Этот режим работает только в Windows NT-based операционных системах. При использовании этого режима чтение и запись в файл реализуются параллельно работе нити, задавшей файловую операцию. Для обеспечения возможности асинхронного режима работы с файлом необходимо в параметре dwFlagsAndAttributes функции CreateFile задать битовый флаг FILE_FLAG_OVERLAPPED.
После этого параметр lpOverlapped у функций чтения и записи в файл должен являться указателем на экземпляр структуры OVERLAPPED, представленной ниже:
typedef struct _OVERLAPPED {
  ULONG_PTR Internal;
  ULONG_PTR InternalHigh;
  DWORD Offset;
  DWORD OffsetHigh;
  HANDLE hEvent;
} OVERLAPPED;
Параметры структуры Offset и OffsetHigh задают начальное смещение от начала файла для выполнения файловой операции. Дескриптор hEvent должен быть верным дескриптором события, порожденного с помощью функции CreateEvent. Параметры Internal и InternalHigh используются самой ОС.
После задания асинхронной операции с файлом функция ReadFile или WriteFile немедленно возвращает управление. После окончания файловой операции событие hEvent переходит в сигнальное состояние и может быть проверено с помощью стандартных WaitFor-функций.
Функция CancelIo немедленно прекращает все ждущие асинхронные файловые операции по заданному дескриптору файла для текущей нити.

 



Задания

11.    Разработать программу, осуществляющую подсчет числа слов в текстовом файле. Чтение файла должно осуществляться параллельно подсчету. Процесс программы должен состоять из одной нити.

                                                           Листинг программы.
#include <stdio.h>
#include <windows.h>

void main()
{
            HANDLE hFile;
            OVERLAPPED over;
            DWORD dByte,dwError;
            int iByteToRead=1;
            BOOL bResult;
            int iWord=0,tek=0,pred=0,iBreak=0,iBegin=1,iEnd=1;      //новое слово - tek=1,pted=0;
           
                       
            over.Offset=0;
            over.OffsetHigh=0;
           
            char cBuffer[1];
            // Создаём событие для контроля за асинхронным чтением
            over.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
            if(over.hEvent==NULL)
            {
                        printf("\nError create event!!!");
                        exit(0);
                        // Ошибка создания события …
            }
           
            hFile=CreateFile("test.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
            if(hFile==INVALID_HANDLE_VALUE)
            {
                        printf("\nError opening file!!!");
                        exit(0);
            }
            while(1)
            {
                        bResult = ReadFile(hFile,cBuffer,iByteToRead,&dByte,&over);
                        // если возникает проблема или асинхронная операция
                        // все еще ожидает обработки ...
                       
                        if (!bResult)
                        {
                                   // решаем что делать с кодом ошибки
                                   switch (dwError = GetLastError())
                                   {
                                   case ERROR_HANDLE_EOF:
                                               {
                                                           // мы достигли конца файла
                                                           // в течение вызова к ReadFile
                                                           iBreak=1;
                                                           break;
                                               }
                                              
                                   case ERROR_IO_PENDING:
                                               {
                                                           // асинхронный ввод-вывод все еще происходит
                                                          
                                                           // сделаем кое-что пока он идет
                                                           //          GoDoSomethingElse() ;
                                                           over.Offset++;
                                                          
                                                           pred=tek;
                                                           if(cBuffer[0]==' '|| cBuffer[0]=='\x0D' || cBuffer[0]=='\n')tek=0;
                                                           else tek=1;
                                                           if(tek==1 && pred==0)iWord++;
                                                           // проверим результат работы асинхронного чтения
                                                           bResult = GetOverlappedResult(hFile, &over,         &dByte, FALSE) ;
                                                          
                                                           // если возникла проблема ...
                                                           if (!bResult)
                                                           {
                                                                       // решаем что делать с кодом ошибки
                                                                       switch (dwError = GetLastError())
                                                                       {
                                                                       case ERROR_HANDLE_EOF:
                                                                                  {
                                                                                              // мы достигли конца файла
                                                                                              // в ходе асинхронной
                                                                                              // операции
                                                                                              iBreak=1;
                                                                                              break;
                                                                                  }
                                                                       default:
                                                                                  {
                                                                                              printf("\nError work to file!!!");
                                                                                              iBreak=1;
                                                                                              break;// решаем что делать с другими случаями ошибок
                                                                                  }
                                                                       }// конец процедуры switch (dwError = GetLastError())
                                                           }
                                                           break;
                                               } // конец процедуры case
                                   default:
                                               {
                                                           printf("\nError work to file!!!");
                                                           iBreak=1;
                                                           break;  // решаем что делать с другими случаями ошибок
                                               }
                                              
                                   } // конец процедуры switch (dwError = GetLastError())
                        } // конец процедуры if
                        if(iBreak==1)break;
                        over.Offset++;
                        pred=tek;
                        if(cBuffer[0]==' ' || cBuffer[0]=='\x0D' || cBuffer[0]=='\n')tek=0;
                        else tek=1;
                        if(tek==1 && pred==0)iWord++;
                       
                       
            }
            printf("\nIn text %d words!!!", iWord);
            getchar();
}

Вывод: изучили способы работы с файлами в Win32 API, изучили асинхронный режим работы с файлами.

Комментариев нет:

Отправить комментарий