Книга: Системное программирование в среде Windows
Пример: преобразование файла с использованием расширенного ввода/вывода
Пример: преобразование файла с использованием расширенного ввода/вывода
Программа 14.3 (atouEX) представляет собой переработанную версию программы 14.1. Эти программы иллюстрируют различие между двумя методами асинхронного ввода/вывода. Программа atouEx аналогична программе 14.1, но большая часть кода, предназначенного для упорядочения ресурсов, перемещена в ней в процедуру завершения, а многие переменные сделаны глобальными, чтобы процедура завершения могла иметь к ним доступ. Вместе с тем, в приложении В показано, что в отношении быстродействия программа atouEx вполне может конкурировать с другими методами, в которых не используется отображение файлов, тогда как программа atouOV работает медленнее.
Программа 14.2. atouEx: преобразование файла с использованием расширенного ввода/вывода
/* Глава 14. atouEX
Преобразование файла из ASCII в Unicode средствами РАСШИРЕННОГО ВВОДА/ВЫВОДА. */
/* atouEX файл1 файл2 */
#include "EvryThng.h"
#define MAX_OVRLP 4
#define REC_SIZE 8096 /* Размер блока не имеет столь важного значения в отношении производительности, как в случае atouOV. */
#define UREC_SIZE 2 * REC_SIZE
static VOID WINAPI ReadDone(DWORD, DWORD, LPOVERLAPPED);
static VOID WINAPI WriteDone(DWORD, DWORD, LPOVERLAPPED);
/* Первая структура OVERLAPPED предназначена для чтения, а вторая — для записи. Структуры и буферы распределяются для каждой предстоящей операции. */
OVERLAPPED OverLapIn[MAX_OVRLP], OverLapOut [MAX_OVRLP];
CHAR AsRec[MAX_OVRLP][REC_SIZE];
WCHAR UnRec[MAX_OVRLP][REC_SIZE];
HANDLE hInputFile, hOutputFile;
LONGLONG nRecord, nDone;
LARGE_INTEGER FileSize;
int _tmain(int argc, LPTSTR argv[]) {
DWORD ic;
LARGE_INTEGER CurPosIn;
hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
hOutputFile = CreateFile(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
FileSize.LowPart = GetFileSize(hInputFile, &FileSize.HighPart);
nRecord = FileSize.QuadPart / REC_SIZE;
if ((FileSize.QuadPart % REC_SIZE) != 0) nRecord++;
CurPosIn.QuadPart = 0;
for (ic = 0; ic < MAX_OVRLP; ic++) {
OverLapIn[ic].hEvent = (HANDLE)ic; /* Перегрузить событие. */
OverLapOut[ic].hEvent = (HANDLE)ic; /* Поля. */
OverLapIn[ic].Offset = CurPosIn.LowPart;
OverLapIn[ic].OffsetHigh = CurPosIn.HighPart;
if (CurPosIn.QuadPart < FileSize.QuadPart) ReadFileEx(hInputFile, AsRec[ic], REC_SIZE, &OverLapIn [ic], ReadDone);
CurPosIn.QuadPart += (LONGLONG)REC_SIZE;
}
/* Выполняются все операции чтения. Войти в состояние дежурного ожидания и оставаться в нем до тех пор, пока не будут обработаны все записи.*/
nDone = 0;
while (nDone < 2 * nRecord) SleepEx(INFINITE, TRUE);
CloseHandle(hInputFile);
CloseHandle(hOutputFile);
_tprintf(_T("Преобразование из ASCII в Unicode завершено.n"));
return 0;
}
static VOID WINAPI ReadDone(DWORD Code, DWORD nBytes, LPOVERLAPPED pOv) {
/* Чтение завершено. Преобразовать данные и инициировать запись. */
LARGE_INTEGER CurPosIn, CurPosOut;
DWORD ic, i;
nDone++;
/* Обработать запись и инициировать операцию записи. */
ic = (DWORD)(pOv->hEvent);
CurPosIn.LowPart = OverLapIn[ic].Offset;
CurPosIn.HighPart = OverLapIn[ic].OffsetHigh;
CurPosOut.QuadPart = (CurPosIn.QuadPart / REC_SIZE) * UREC_SIZE;
OverLapOut[ic].Offset = CurPosOut.LowPart;
OverLapOut[ic].OffsetHigh = CurPosOut.HighPart;
/* Преобразовать запись из ASCII в Unicode. */
for (i = 0; i < nBytes; i++) UnRec[ic][i] = AsRec[ic][i];
WriteFileEx(hOutputFile, UnRec[ic], nBytes*2, &OverLapOut[ic], WriteDone);
/* Подготовить структуру OVERLAPPED для следующего чтения. */
CurPosIn.QuadPart += REC_SIZE * (LONGLONG)(MAX_OVRLP);
OverLapIn[ic].Offset = CurPosIn.LowPart;
OverLapIn[ic].OffsetHigh = CurPosIn.HighPart;
return;
}
static VOID WINAPI WriteDone(DWORD Code, DWORD nBytes, LPOVERLAPPED pOv) {
/* Запись завершена. Инициировать следующую операцию чтения. */
LARGE_INTECER CurPosIn;
DWORD ic;
nDone++;
ic = (DWORD)(pOv->hEvent);
CurPosIn.LowPart = OverLapIn[ic].Offset;
CurPosIn.HighPart = OverLapIn[ic].OffsetHigh;
if (CurPosIn.QuadPart < FileSize.QuadPart) {
ReadFileEx(hInputFile, AsRec[ic], REC_SIZE, &OverLapIn[ic], ReadDone);
}
return;
}
- Обзор методов асинхронного ввода/вывода Windows
- Перекрывающийся ввод/вывод
- Пример: использование дескриптора файла в качестве объекта синхронизации
- Пример: преобразование файлов с использованием перекрывающегося ввода/вывода и множественной буферизации
- Расширенный ввод/вывод с использованием процедуры завершения
- Пример: преобразование файла с использованием расширенного ввода/вывода
- Асинхронный ввод/вывод сиспользованием нескольких потоков
- Таймеры ожидания
- Пример: использование таймера ожидания
- Порты завершения ввода/вывода
- Пример: сервер, использующий порты завершения ввода/вывода
- Резюме
- Упражнения
- Пример: преобразование файла с использованием расширенного ввода
- Пример установочного скрипта
- Пример из практики
- Восстановление с использованием инструмента gbak
- Преобразование XML в реляционную базу данных
- ПРИМЕР ПРОСТОЙ ПРОГРАММЫ НА ЯЗЫКЕ СИ
- Эффективная работа с временными файлами сортировки
- Примеры получения статистики
- Пример применения метода «пять почему»
- Единое имя файла параметров InterBase
- Параметры конфигурационного файла InterBase
- Пример 12-8. Частота встречаемости отдельных слов