Опубликован: 02.02.2011 | Доступ: свободный | Студентов: 3318 / 936 | Оценка: 4.43 / 3.57 | Длительность: 33:06:00
Специальности: Программист
Лекция 22:

Прямой доступ к данным файла

< Лекция 21 || Лекция 22: 123 || Лекция 23 >

Функция записи в файл

Запись в файл на нижнем уровне осуществляется побайтно, без буферизации, с помощью функции write.

Синтаксис:

int write(int fd, char *buffer,int count);

где переменные fd, buffer, count имеют тот же смысл, что и для вызова функции read.

Функция возвращает количество фактически переданных байтов.

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

Функция прямого доступа к файлу

Функция read при корректном выполнении осуществляет последовательное чтение данных из файла. Однако при работе с файлами на нижнем уровне можно изменять порядок доступа к данным с последовательного на произвольный. Для этого используется функция fseek.

Синтаксис:

int fseek(FILE *f, long off, int org);

где fуказатель на файл;

off – позиция смещения;

org – начало отсчета.

Смещение off задается выражением или переменной и может быть отрицательным, то есть возможно перемещение как в прямом, так и в обратном направлениях. Начало отсчета org задается одной из определенных в файле <stdio.h> констант.

Константы, задающие начало отсчета
Константа Значение Описание
SEEK_SET 0 начало файла
SEEK_CUR 1 текущая позиция
SEEK_END 2 конец файла

Функция возвращает 0, если перемещение в потоке выполнено успешно, иначе возвращает ненулевое значение.

Функцию fseek следует использовать только при работе с двоичными файлами. В текстовых файлах начало отсчета org должно быть установлено как SEEK_SET, а смещение указывается относительно начала файла (возможно нулевое смещение, которое интерпретируется как позиционирование в начало файла).

Например, для текстовых файлов:

fseek(f,0L,SEEK_SET); 
//перемещение к началу потока из текущей позиции
fseek(f,0L,SEEK_END); 
//перемещение к концу потока из текущей позиции

Например, для двоичных файлов:

fseek(f,(long)sizeof(a),SEEK_SET); 
//перемещение вперед от начала на длину переменной а
fseek(f,-(long)sizeof(a),SEEK_CUR); 
//перемещение назад от текущей позиции на длину переменной а

Кроме этой функции, для прямого доступа к файлу используются функции:

long ftell(FILE *f);
//получает значение указателя текущей позиции в потоке
void rewind(FILE *f);
//устанавливает значение указателя на начало потока

Пример 1. Использование в программе функций доступа к данным на нижнем уровне.

#include "stdafx.h"
#include <iostream>
using namespace std;
#include <fcntl.h> 
#include <sys\stat.h>
#include <io.h>
int _tmain(int argc, _TCHAR* argv[]){
  int fh1, fh2;
  //открытие файла на нижнем уровне
  fh1 = open("data1.dat", O_RDONLY);
  //проверка корректности открытия файла
  if (fh1 == -1)
    perror("Open failed on input file");
  fh2 = open("data2.dat",O_WRONLY|O_TRUNC|O_CREAT,S_IREAD|S_IWRITE);
  if (fh2 == -1)
    perror("Open failed on output file");
  system("pause");
  return 0;
}

Пример 2. Использование в программе позиционирования файлового указателя с помощью функции fseek в двоичном файле.

#include "stdafx.h"
#include <iostream>
using namespace std;
#include <io.h>
int _tmain(int argc, _TCHAR* argv[]){
  FILE *f;//указатель на двоичный файл
  int i,n=10;
  char s[]="String";
  float r;
  f=fopen("file_bin","wb");
  //создание двоичного файла для записи
  for(i=1;i<=n;i++){ 
    r=pow(i,1.0/3);
    fwrite(s,sizeof(s),1,f);
    //запись строки String в файл
    fwrite(&i,sizeof(int),1,f);
    //запись целого числа (номера строки) в файл
    fwrite(&r,sizeof(float),1,f);
    //запись вещественного числа (корня кубического) в файл
    printf("\n%s %d %f",s,i,r);//контрольный вывод на экран
  }
  fclose(f);//закрытие файла
  printf("\n");
  f=fopen("file_bin","rb");
  //открытие двоичного файла для чтения
  for(i=n; i>0; i--) {
    //перемещение указателя файла
    fseek(f,(i-1)*(sizeof(s)+sizeof(int)+sizeof(float)),SEEK_SET);
    fread(&s,sizeof(s),1,f);//чтение строки
    fread(&n,sizeof(int),1,f);//чтение целого числа
    fread(&r,sizeof(float),1,f);
    //чтение вещественного числа
    printf("\n%s %d %f",s,n,r);
    //вывод на экран содержимого файла
  }  
  system("pause");
  return 0;
}

Ключевые термины

Дескриптор – это целое значение, характеризующее размещение информации об открытом файле во внутренних таблицах операционной системы.

Прямой доступ к файлу – это доступ к содержимому файла с помощью средств операционной системы.

Разделенный доступ к файлу – это организация работы с одним и тем же файлом нескольких пользователей одновременно.

Смещение – это относительная координата перемещения указателя при обращении к данным файла на нижнем уровне.

Тип доступа – это разрешенное действие над файлом, оформленное с помощью целочисленных констант.

Тип операций – это выполняемая операция над файлом, оформленная с помощью целочисленных констант.

Функции ввода-вывода низкого уровня (прямого доступа) – это функции, осуществляющие обмен с файлами или периферийными устройствами путем прямого обращения к соответствующим функциям операционной системы.

Краткие итоги

  1. В С++ доступ к файлам можно осуществлять на потоковом и низком уровнях.
  2. В отличие от потокового уровня, низкоуровневый ввод-вывод осуществляется побайтно без буферизации данных, без приведения их к базовым типам и использует ресурсы операционной системы.
  3. Работа с файлами на низком уровне осуществляется с помощью средств прямого доступа к данным файла.
  4. Открытому файлу на нижнем уровне соответствует файловый дескриптор.
  5. Режимы доступа к данным файла на нижнем уровне определяются с помощью констант типа доступа и типа операций.
  6. В С++ предусмотрен разделенный режим работы с файлами на нижнем уровне.
  7. Открытый файл должен быть закрыт после использования.
  8. Порядок доступа к байтам файла можно изменять функционально путем указания относительного смещения. Смещение может быть положительным (движение к концу файла), отрицательным (движение к началу файла) или нулевым (нет смещения).
  9. Запрос на чтение данных на нижнем уровне завершается при считывании заданного числа байтов, при достижении конца файла или при возникновении системной ошибки чтения.
< Лекция 21 || Лекция 22: 123 || Лекция 23 >
Денис Курбатов
Денис Курбатов
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!