Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

MS-DOS для программиста

© Александр Фролов, Григорий Фролов
Том 19, М.: Диалог-МИФИ, 1995, 253 стр.

[Назад] [Содеожание] [Дальше]

3.6. Позиционирование

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

Установка файлового указателя

Установить файловый указатель в нужную вам позицию можно с помощью функции 42h прерывания INT 21h :

На входе: AH 42h
AL Метод кодирования смещения:
00h - абсолютное смещение от начала файла;01h - смещение от текущей позиции;02h - смещение от конца файла
BX Идентификатор открытого файла
CX Старший байт смещения
DX Младший байт смещения
На выходе: AX Код ошибки, если установлен флаг переноса CF;Младший байт текущей позиции, если флаг переноса CF сброшен
DX Старший байт текущей позиции

Функция 42h позволяет указывать новое значение указателя либо как абсолютное смещение от начала файла, либо как смещение от текущей позиции, либо как смещение от конца файла. В последних двух случаях используется смещение со знаком. Для указания смещения или абсолютной позиции программа должна задать в регистрах CX, DX соответствующее 32-битное значение.

Что произойдет, если при использовании методов кодирования 01h или 02h попытаться установить указатель позиции до начала файла?

Функция 42h при этом не возвратит признак ошибки, однако если будет сделана попытка прочитать или записать данные, то соответствующая функция чтения/записи завершится с ошибкой.

Определение размера файла

Если использовать метод кодирования 02h и при этом задать нулевое смещение, функция установит указатель на конец файла. Это обстоятельство может быть использовано для определения размера файла в байтах.

Функции библиотеки Borland C++

Стандартная библиотека Borland C++ содержит функции, предназначенные для управления файловым указателем позиции и получения текущего значения этого указателя. Это функции lseek , tell , filelength .

lseek

Функция lseek работает аналогично только что описанной функции 42h. Приведем ее прототип:

long lseek (int handle, long offset, int origin);

Первый параметр определяет файл, для которого выполняется операция позиционирования. Параметр offset определяет смещение. Последний параметр задает метод кодирования смещения. Он может принимать следующие значения, описанные в фале stdio.h:

Значение Описание
SEEK_SET Абсолютное смещение от начала файла
SEEK_CUR Смещение относительно текущей позиции
SEEK_END Смещение относительно конца файла

Функция возвращает величину текущего смещения в байтах относительно начала файла или -1 в случае ошибки. Как и для остальных функций библиотеки, код ошибки находится в глобальной переменной errno.

filelength

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

long filelength (int handle);

Эта функция возвращает размер файла в байтах. Файл задается параметром handle. В случае ошибки функция возвращает значение -1.

tell

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

long tell (int handle);

Эта функция возвращает текущую позицию для файла, определенного параметром handle, или -1 в случае ошибки.

Программа SETPOS

Для демонстрации использования функций позиционирования приведем простую программу SETPOS (листинг 3.5), которая для заданного файла и позиции внутри файла отображает содержимое одного байта. Дополнительно программа определяет размер файла и текущую позицию после чтения байта.


Листинг 3.5. Файл setpos\setpos.cpp


#include <io.h>
#include <stdio.h>
#include <fcntl.h>

int main(void)
{
  int handle;
  long position, length;
  char buffer[2], fname[80];

  // Запрашиваем имя файла, с которым будем работать
  printf("Введите имя файла: ");
  gets(fname);

  // Открываем файл
  handle = open (fname, O_BINARY  | O_RDONLY );

  // Если такого файла нет, выводим сообщение об ошибке
  // и завершаем работу программы
  if(handle == -1)
  {
    printf("\nНет такого файла!");
    return(-1);
  }

  // Определяем и выводим на экран
  // размер файла в байтах
  length = filelength (handle);

  printf("\nДлина файла %s составляет %ld байт\n",
    fname, length);

  // Запрашиваем позицию для чтения и отображения байта
  do
  {
    printf("Введите позицию: ");
    scanf ("%ld", &position);
  } while(position > length);

  // Устанавливаем заданную позицию
  lseek (handle, position, SEEK_SET );

  // Читаем один байт в буфер, начиная с установленной
  // позиции
  if(read (handle, buffer, 1) == -1)
  {
    // Для вывода сообщения об ошибке используем
    // функцию perror(), которая добавляет к сообщению,
    // заданному в параметре, расшифрованное
    // системное сообщение об ошибке.
    // Код ошибки функция perror() берет
    // из переменной errno
    perror("Ошибка при чтении");
    return(-1);
  }

  // Выводим считанный байт на экран
  printf( "Смещение: %ld; байт: %02.2x ('%c')\n",
    position, (unsigned char)*buffer, *buffer);

  // Определяем текущую позицию и выводим ее
  // на экран
  position = tell (handle);
  printf("\nТекущая позиция в файле: %ld\n", position);

  // Закрываем файл
  close (handle);
  return 0;
}

[Назад] [Содеожание] [Дальше]