|
| БЕСПЛАТНАЯ ежедневная online лотерея! Выигрывай каждый день БЕСПЛАТНО! |
|
|
Reading, Writing, and Locking Files
The ReadFile function requires a file handle that is open for reading, or reading and writing. ReadFile copies a specified number of bytes, from the current position up to the end of the file, to a specified buffer. The current position is either the current file pointer setting or the Offset and OffsetHigh members of the specified OVERLAPPED structure. The function returns the actual number of bytes read in a variable specified by its fourth parameter.
The WriteFile function requires a file handle that is open for writing, or writing and reading. WriteFile copies a specified number of bytes, from the current position up to the end of the buffer, to a specified file. The function returns the actual number of bytes written in a variable specified by its fourth parameter. The following example illustrates a possible flow for using callback completion asynchronous I/O. Completion Routine:
VOID IoCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { // If an I/O error occurs, display the error and exit. if (dwErrorCode) { printf("FATAL I/O Error %ld I/O Context %lx.%lx\n", dwErrorCode, lpOverlapped, lpOverlapped->hEvent); ExitProcess(dwErrorCode); } LocalFree(lpOverlapped); }
Main Thread:
VOID IoWorkerThread(VOID) { HANDLE HandleVector[2]; DWORD CompletionStatus; PIOREQUEST IoRequestPacket; LPOVERLAPPED Overlapped; BOOL IoOperationStatus; HandleVector[0] = IoWorkerListLock; HandleVector[1] = IoWorkerListSemaphore; for(;;) { // Do an alertable wait on the handle vector. Both objects // being signaled at the same time means that there is an // I/O request in the queue and the caller has exclusive
// access to the queue. CompletionStatus = WaitForMultipleObjectsEx(2, HandleVector, TRUE, INFINITE, TRUE); // If the wait failed, error out. if (CompletionStatus == 0xFFFFFFFF) { printf("FATAL WAIT ERROR %ld\n", GetLastError()); ExitProcess(1); } // If an I/O completion occurred, wait for another // I/O request or I/O completion. if (CompletionStatus != WAIT_IO_COMPLETION) {
// The wait was satisfied. Ownership of the I/O // request queue is exclusive, and there is something in // the queue. To insert something in the queue, the // inserter gets the list lock (mutex), inserts an entry, // signals the list semaphore, and finally releases the // list lock. IoRequestPacket = RemoveHeadList(&IoRequestList); ReleaseMutex(IoWorkerListLock); // Allocate an overlapped structure.
Overlapped = LocalAlloc(LMEM_ZEROINIT, sizeof(OVERLAPPED)); if (!Overlapped) { printf("FATAL allocation error\n"); ExitProcess(1); } Overlapped->Offset = IoRequestPacket->Offset; Overlapped->OffsetHigh = IoRequestPacket->OffsetHigh; Overlapped->hEvent = IoRequestPacket->dwAdditionalIoContext; if (IoRequestPacket->bRead) {
IoOperationStatus = ReadFileEx(IoRequestPacket->hFile, IoRequestPacket->lpBuffer, IoRequestPacket->dwTransferCount, Overlapped, IoCompletionRoutine); } else { IoOperationStatus = WriteFileEx(IoRequestPacket->hFile, IoRequestPacket->lpBuffer, IoRequestPacket->dwTransferCount,
Overlapped, IoCompletionRoutine); } // Test to see if the I/O was queued successfully. if (!IoOperationStatus) { printf("FATAL I/O Error %ld I/O Context %lx.%lx\n", GetLastError(), Overlapped, Overlapped->hEvent); ExitProcess(1); } // The I/O queued successfully. Go back into the // alertable wait for I/O completion or for
// more I/O requests. } } }
The SetFilePointer function moves the file pointer a specified number of bytes, relative to the beginning or end of the file, or the file pointer's current position. If a positive number of bytes is specified, SetFilePointer moves the file pointer toward the end of the file; a negative value moves the pointer toward the beginning of the file. The following example appends one file to the end of another file. The application opens two files by using CreateFile: ONE.TXT is opened for reading, and TWO.TXT is opened for writing. Then the application appends the contents of ONE.TXT to the end of TWO.TXT by reading and writing 4K blocks by using ReadFile and WriteFile. Before writing to the second file, the application sets the second file's pointer to the end of the file by using SetFilePointer and locks the area to be written by using LockFile. This prevents another process from accessing the area while the write is in progress. After each write operation, UnlockFile unlocks the locked area.
HANDLE hFile; HANDLE hAppend; DWORD dwBytesRead, dwBytesWritten, dwPos; char buff[4096]; // Open the existing file. hFile = CreateFile("ONE.TXT", // open ONE.TXT GENERIC_READ, // open for reading 0, // do not share NULL, // no security OPEN_EXISTING, // existing file only FILE_ATTRIBUTE_NORMAL, // normal file NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open ONE."); // process error } // Open the existing file, or if the file does not exist, // create a new file. hAppend = CreateFile("TWO.TXT", // open TWO.TXT GENERIC_WRITE, // open for writing 0, // do not share NULL, // no security OPEN_ALWAYS, // open or create FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template if (hAppend == INVALID_HANDLE_VALUE) { ErrorHandler("Could not open TWO."); // process error } // Append the first file to the end of the second file. // Lock the second file to prevent another process from // accessing it while writing to it. Unlock the // file when writing is finished. do { if (ReadFile(hFile, buff, 4096, &dwBytesRead, NULL)) { dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END);
LockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0); WriteFile(hAppend, buff, dwBytesRead, &dwBytesWritten, NULL); UnlockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0); } } while (dwBytesRead == 4096); // Close both files. CloseHandle(hFile); CloseHandle(hAppend);
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
Чтение, пишущий, и Запирая Файлы
Функция ReadFile требует файловую ручку, которая открытая для чтения, или чтения и сочинение. ReadFile КОПИРУЕТ определенное количество байтов, из текущей позиции вплоть до конца файла, в определенный буфер. Текущая позиция - или текущая файловая установка указателя или Компенсация и участники OffsetHigh определенной ПЕРЕКРЫТОЙ структуры. Функция возвращает фактическое количество байтов прочитанных в переменной определенной своим четвертым параметром.
Функция WriteFile требует файловую ручку, которая открытая для сочинения, или сочинения и чтение. WriteFile КОПИРУЕТ определенное количество байтов, из текущей позиции вплоть до конца буфера, в определенный файл. Функция возвращает фактическое количество байтов записанных в переменной определенной своим четвертым параметром. Следующий пример иллюстрирует возможный поток для использования завершения возврата асинхронного В/В. Программа Завершения:
ПУСТОТА IoCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { // Если ошибка В/В происходит, отобразите ошибку и выход. если (dwErrorCode) { printf(Ошибка "FATAL В/В %Контекст ld В/В %lx.%lx\n", dwErrorCode, lpOverlapped, lpOverlapped->hEvent); ExitProcess(dwErrorCode); } LocalFree(lpOverlapped); }
Основная Резьба:
ПУСТОТА IoWorkerThread(ПУСТОТА) { ПРООПЕРИРУЙТЕ HandleVector[2]; DWORD CompletionStatus; PIOREQUEST IoRequestPacket; LPOVERLAPPED ПЕРЕКРЫТ; BOOL IoOperationStatus; HandleVector[0] = IoWorkerListLock; HandleVector[1] = IoWorkerListSemaphore; для(;;) { // Сделайте ожиданием alertable на векторе ручки. Оба объекта // сигнализированное в то же самое время означает, что есть // просьба В/В в очереди и вызывающий оператор имеет исключительный
// доступ к очереди. CompletionStatus = WaitForMultipleObjectsEx(2, HandleVector, TRUE, БЕСКОНЕЧНАЯ, ИСТИНА); // Если ожидание терпело бы неудачу, ошибку. если (CompletionStatus == 0xFFFFFFFF) { printf(ОШИБКА ОЖИДАНИЯ "FATAL %ld\n", GetLastError()); ExitProcess(1); } // Если завершение В/В происходило бы, подождите другое // просьбу В/В или завершение В/В. если (CompletionStatus != WAIT_IO_COMPLETION) {
// Ожидание было удовлетворено. Собственность на очередь просьбы В/В // - исключительная, и есть что-то в // очередь. Для того, чтобы включать что-то в очереди, // inserter получает замок списка (mutex), включает вход, // сигнализирует семафор списка, и наконец выпускает // замок списка. IoRequestPacket = RemoveHeadList(&IoRequestList); ReleaseMutex(IoWorkerListLock); // Распределите перекрытую структуру.
Перекрывшее = LocalAlloc(LMEM_ZEROINIT, sizeof(ПЕРЕКРЫТЫЙ)); если (!Перекрытое) { printf(распределение "FATAL error\n"); ExitProcess(1); } Overlapped->Offset = IoRequestPacket->Offset; Overlapped->OffsetHigh = IoRequestPacket->OffsetHigh; Overlapped->hEvent = IoRequestPacket->dwAdditionalIoContext; если (IoRequestPacket->bRead) {
IoOperationStatus = ReadFileEx(IoRequestPacket->hFile, IoRequestPacket->lpBuffer, IoRequestPacket->dwTransferCount, ПЕРЕКРЫТЫЙ, IoCompletionRoutine); } еще { IoOperationStatus = WriteFileEx(IoRequestPacket->hFile, IoRequestPacket->lpBuffer, IoRequestPacket->dwTransferCount,
Перекрытое, IoCompletionRoutine); } // Тест, чтобы видеть если В/В ставилось в очередь успешно. если (!IoOperationStatus) { printf(ОШИБКА "FATAL В/В %Контекст ld В/В %lx.%lx\n", GetLastError(), Перекрытое, Overlapped->hEvent); ExitProcess(1); } // В/В ставилось в очередь успешно. Возвращайтесь на // alertable завершение ожидания В/В или для
// более В/В просится. } } }
Функция SetFilePointer перемещает файловому указателю определенное количество байтов, относительно начала или конца файла, или текущей позиции файлового указателя. Если положительное количество байтов определено, SetFilePointer перемещает файловый указатель по отношению к концу файла; отрицательная величина перемещает указатель по отношению к началу файла. Следующий пример добавляет один файл в конец другого файла. Приложение открывает два файла используя CreateFile: ONE.TXT открыт для чтения, и TWO.TXT открыт для сочинения. Затем приложение добавляет содержание ONE.TXT в конец TWO.TXT читая и пиша блоков 4K используя ReadFile и WriteFile. Перед сочинением во второй файл, приложение устанавливает второй файловый указатель в конец файла используя SetFilePointer и запирает область, которая нужно писать использованием LockFile. Это мешает процесс чтобы получать область тогда как писать осуществляется. После каждого действия записи, UnlockFile деблокирует закрытую область.
ПРООПЕРИРУЙТЕ hFile; ПРООПЕРИРУЙТЕ hAppend; DWORD dwBytesRead, dwBytesWritten, dwPos; символ полирует[4096]; // Открытый существующий файл. hFile = CreateFile("ONE.TXT", // Открытый ONE.TXT GENERIC_READ, // открытый для чтения 0, // не не распространять НЕДЕЙСТВИТЕЛЬНУЮ, // никакую безопасность OPEN_EXISTING, // существующий файл только FILE_ATTRIBUTE_NORMAL, // нормальный файловый НЕДЕЙСТВИТЕЛЬНЫЙ); // никакой attr. шаблон
если (hFile == INVALID_HANDLE_VALUE) { ErrorHandler("Could не открытый ОДИН."); // ошибка процесса } // Открытый существующий файл, или если файл не существует, // создавать новый файл. hAppend = CreateFile("TWO.TXT", // Открытый TWO.TXT GENERIC_WRITE, // открытый для сочинения 0, // не распространять НЕДЕЙСТВИТЕЛЬНЫЙ, // никакая безопасность OPEN_ALWAYS, // открывать или создавать FILE_ATTRIBUTE_NORMAL, // нормальный файл
НЕДЕЙСТВИТЕЛЬНЫЙ); // никакой attr. шаблон если (hAppend == INVALID_HANDLE_VALUE) { ErrorHandler("Could не открывать ДВА."); // ошибка процесса } // Добавьте первый файл в конец второго файла. // Замок второй файл, чтобы предохранять другой процесс от // доступа это при сочинении этому. Деблокируйте // файл когда сочинение завершено. сделайте { если (ReadFile(hFile, отполируйте, 4096, &dwBytesRead, НЕДЕЙСТВИТЕЛЬНОЕ)) { dwPos = SetFilePointer(hAppend, 0, НЕДЕЙСТВИТЕЛЬНЫЙ, FILE_END);
LockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0); WriteFile(hAppend, БЕЖ, dwBytesRead, &dwBytesWritten, НЕДЕЙСТВИТЕЛЬНОЕ); UnlockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0); } } пока (dwBytesRead == 4096); // Закрытые оба файла. CloseHandle(hFile); CloseHandle(hAppend);
|
|
|
|
| |