Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 2.DOC
Скачиваний:
91
Добавлен:
10.05.2014
Размер:
827.9 Кб
Скачать

Запись и чтение файла

При работе с данными, содержащимися в файле, чаще других используются три функции: записи в файл WriteFile(), чтения из файлаReadFile() и установки файлового указателяSetFilePointer().

Функции чтения и записи имеют практически одинаковые прототипы:

BOOL ReadFile(HANDLE hFile,

LPVOID lpBuffer,

DWORD nNumberOfBytesToRead,

LPDWORD lpNumberOfBytesRead,

LPOVERLAPPED lpOverlapped);

BOOL WriteFile(HANDLE hFile,

LPCVOID lpBuffer,

DWORD nNumberOfBytesToWrite,

LPDWORD lpNumberOfBytesWritten,

LPOVERLAPPED lpOverlapped);

Параметр hFileобозначает полученный от функцииCreateFile()дескриптор созданного или открытого файла.

Параметр lpBufferпредставляет собой адрес программного буфера, предназначенного для хранения данных, записываемых в файл или считываемых из файла. Обобщенный тип этого буфера –LPVOIDилиLPCVOID– позволяет обмениваться с файлом данными любой организации – отдельными байтами или скалярными переменными большей длины, а также массивами и структурами.

Третий параметр рассматриваемых функций определяет заказываемый объем пересылаемых данных (в байтах).

Четвертый параметр является адресом программной переменной типа DWORD, в которую после завершения передачи данных будет записано истинное число переданных байтов. Этой переменной можно воспользоваться для контроля правильности выполненной операции записи или чтения.

Последний параметр, lpOverlapped, используется в тех случаях, когда операции над файлом предполагается осуществлять в асинхронном режиме (его еще называют режимом с перекрытием). Обычно программа, поставив запрос на чтение данных из файла или запись данных в файл, останавливается до завершения этой операции, хотя в течение всего этого времени процессор почти свободен и мог бы выполнять полезную работу. Такой режим выполнения программы называется синхронным. Некоторые операционные системы, в частности, WindowsNTи Windows 2000, позволяют выполнять асинхронные операции над файлами. Суть асинхронного режима заключается в том, что система, запустив операцию ввода или вывода, возвращает управление в программу, которая может таким образом продолжить выполнение параллельно с дисковой операцией ввода-вывода. В случае обычных операций чтения или записи значение параметраlpOverlappedдолжно быть равноNULL.

Функция SetFilePointer()установки файлового указателя служит для перемещения указателя в файле на заданный байт, чтобы последующая операция чтения или записи выполнила пересылку данных не с начала файла, а от положения указателя. Прототип этой функции имеет следующий вид:

DWORD SetFilePointer(HANDLE hFile,LONG lDistanceToMove,

PLONG lpDistanceToMoveHigh,DWORD dwMoveMethod);

Параметр hFileобозначает полученный от функцииCreateFile()дескриптор созданного или открытого файла.

Параметр lDistanceToMoveзадает 32-битовое смещение в файле до точки установки указателя.

Параметр lpDistanceToMoveHighявляется адресом старшей половины смещения указателя, если смещение характеризуется 64-битовым значением. Обычно здесь указываетсяNULL.

Последний параметр dwMoveMethodопределяет способ установки указателя. Этот параметр может принимать три значения:

FILE_BEGIN– указатель устанавливается от начала файла и, следовательно, рассматривается как число без знака. Максимальное смещение в файле (если не использовать параметрlpDistanceToMoveHigh) достигает 232 - 2 = 4 Гбайт - 2;

FILE_CURRENT– указатель устанавливается от текущей позиции указателя и, следовательно, рассматривается как число со знаком, что позволяет смещать указатель как вперед, так и назад от текущего положения в пределах до 2 Гбайт;

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

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

struct GOODS{//Структура, описывающая изделия на складе

int Nmb;//Номер изделия

int Price;//Цена изделия

};

const int N=1000000;//Пусть на складе миллион образцов изделий

GOODS Stock[N];//Создадим в памяти массив для всех изделий

GOODS Unit1;//Структурная переменная для одного изделия

DWORD dwCount;//Для функций чтения/записи

... //Заполним массив структур данными

/*Создадим новый файл*/

HANDLE hFile=CreateFile("stock.dat",

GENERIC_READ|GENERIC_WRITE,

0,NULL,CREATE_ALWAYS,0,NULL);

/*Запишем в файл весь массив структурных переменных*/

WriteFile(hFile,Stock,sizeof(Stock),&dwCount,NULL);

/*Сместим указатель на последнюю записьи прочитаем ее*/

SetFilePointer(hFile,sizeof(GOODS)*(-1),NULL,FILE_END);

ReadFile(hFile,&Unit1,sizeof(GOODS),&dwCount,NULL);

CloseHandle(hFile);//Закроем файл (нет необходимости)

С таким же успехом и даже более наглядно было бы в операциях записи, установки указатели и чтения указывать количество записываемых байтов в виде числа. Поскольку каждое число типа intтребует для своего хранения четыре байта, то каждая структурная переменная типаGOODSзанимает в памяти 8 байт, а весь массив – 8000000 байт. Поэтому запись в файл можно выполнить таким образом:

WriteFile(hFile,Stock,8000000,&dwCount,NULL);

а, например, установку указателя так:

SetFilePointer(hFile, -8,NULL,FILE_END);

или так:

SetFilePointer(hFile, 7999992,NULL,FILE_BEGIN);

Следует заметить, что при работе с большими массивами (превышающими по объему 1 Мбайт) надо специально подумать об их размещении в памяти. Если массив объявлен как локальная переменная, то для него должно быть выделено место в стеке, а размер стека по умолчанию ограничивается системой программирования. Впрочем, изменив настройки системы программирования, можно увеличить стек до нужного размера.