Функция fseek()

Наибольшими возможностями позиционирования указателя потока обладает функция int fseek (FILE *f, long offset, int from). Она сдвигает указатель в файле f на offset байт от положения, указанного третьим параметром from.

Чаще всего from принимает значение SEEK_SET или, что то же самое, нулевое значение. Тогда указатель файла перемещается на offset байт “вперёд” от начала потока в сторону конца файла, если offset>=0. В этом случае offset задаёт порядковый номер байта, на который надо установить указатель чтения-записи. При таком нулевом значении параметра from параметр offset не должен быть отрицательным. Например,

int a; fseek(f, 20, SEEK_SET); a=fgetc(f); //??????

прочитает информацию, начиная с 20-го байта двоичного файла, который желательно открывать с режимом “rb”.

Если from=SEEK_END, что соответствует целому числу 2,то при неположительном значении параметра offset указатель файла перемещается на | offset| байт “назад” от конца потока в сторону начала файла. При таком значении параметра from параметр offset не должен быть положительным. В противном случае мы “выйдем” за границу файла.

Если from=SEEK_CUR, что соответствует целому числу 1, то можно “продвигаться” на offset байт “вперёд” от текущей позиции указателя при offset>0, или “назад” к началу файла, если offset<0.

Функция fseek() возвращает 0 в случае успешного выполнения и ненулевое значение в случае ошибки.

Пример 1. Прямой доступ к файлу. Прочитать и вывести на экран n-й одномерный массив фиксированной размерности m, (n-2)-й массив, (n-4)-й массив и т. д. до начала файла.

const m=5,

n=8;

FILE *arf;

// Создание файла. Объяснение смотри в 3.2

void MyCr()

{ int a[m];

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat","wb");

printf("\n");

for (int i=0; i<n;i++)

{ cout<<endl;

for (int j=0;j<m;j++)

{ a[j]=(i+1)*(j+1);

printf("%5d",a[j]);

}

fwrite (a, sizeof(a),1, arf);

}

fclose(arf); cout<<"\nFile was created"; }

// Просмотр файла. Объяснение смотри в 3.2

void MyRead()

{ int a[m];

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat","rb");

fread(a,sizeof(a),1,arf);

while (!feof(arf))

{

printf("\n");

for (int j=0;j<m;j++)

printf("%5d",a[j]);

fread(a,m*sizeof(int),1,arf);

}

fclose(arf);

}

/* Вариант 1. Указатель файла перемещаем, используя в функции fseek () позицию начала файла, т. е. в качестве последнего параметра этой функции используем SEEK_SET */

void MyRead1()

{ int a[m];

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat","rb");

for (int i=1; i<=n;i+=2)

{ fseek(arf, (n-i)*sizeof(a),SEEK_SET);

fread(a,sizeof(a),1,arf);

printf("\n");

for (int j=0;j<m;j++)

printf("%5d",a[j]);

}

fclose(arf);

}

/* Вариант 2. Указатель файла перемещаем, используя в функции fseek () позицию конца файла SEEK_END */

void MyRead2()

{ int a[m];

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat","rb");

for (int i=1; i<=n;i+=2)

{ fseek(arf, -i*sizeof(a),SEEK_END);

fread(a,sizeof(a),1,arf);

printf("\n");

for (int j=0;j<m;j++)

printf("%5d",a[j]);

}

fclose(arf); }

/* Вариант 3. Указатель файла перемещаем, используя в функции fseek () текущую позицию файла SEEK_CUR */

void MyRead3()

{ int a[m];

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat","rb");

fseek(arf, -1*sizeof(a), SEEK_END);

for (int i=0; i<n/2;i++)

{ fread(a,sizeof(a),1,arf);

printf("\n");

for (int j=0;j<m;j++)

printf("%5d",a[j]);

fseek(arf, -3*sizeof(a),SEEK_CUR);

}

fclose(arf); }

int main()

{ int flag; while (1)

{ cout << "\n1 -- CREATE"<<endl<<

"2 -- READ"<<endl<<

"3 -- Read1"<<endl<<

"4 -- Read2"<<endl<<

"5 -- Read3"<<endl<<

"0 -- EXIT"<<endl;

cin>>flag;

switch (flag)

{ case 1: MyCr(); break;

case 2: MyRead(); break;

case 3: MyRead1(); break;

case 4: MyRead2(); break;

case 5: MyRead3(); break;

case 0: return 0;

}

}

}

4.2. Замена записи. Функции ftell, fgetpos, fsetpos, rewind.

В предыдущий проект (п. 4.1) добавим ещё одну функцию, которая в файле одномерных массивов меняет массив с номером nChange. Замена выполняется в следующей последовательности:

void MyChange(int nChange)

{

// nChange — номер массива (записи), который меняем

// 1) Открываем в режиме "rb+".

arf= fopen("d:\\ANA\\cpp\\2004_05\\farr2.dat ", "rb+");

// 2) Переходим на начало массива с номером nChange

fseek(arf, (nChange-1) * sizeof(a), 0);

/* 3) Запоминаем номер первого байта начала массива c номером nChange Нумерация байт с начала файла */

long p; p=ftell(arf); // or fgetpos(arf,&p);

cout<<endl<<"p="<<p<<endl; // p=20, если nChange=2

// 4) Читаем массив c номером nChange в оперативную память

fread(a, sizeof(a), 1, arf);

printf("\n Массив, который будем менять");

/* 5) Выводим прочитанный массив и меняем его по заданному алгоритму */

for(j=0;j<m;j++)

{ printf("%d ",a[j]);

a[j]=a[j]*10;

}

/* 6) После выполнения функции fread указатель чтения-записи переместился “вперёд” к концу файла на один массив, т. е. на начало следующего массива с номером nChange+1. Поэтому устанавливаем позицию указателя чтения-записи на начало того же уже прочитанного массива c номером nChange, чтобы на это место записать изменённый массив. В нашем примере для наглядности при выводе каждый элемент увеличили в 10 раз.*/

fsetpos(arf,&p);

/* 7) На место старого массива записываем новый, изменённый массив. */

fwrite(a,sizeof(a),1, arf);

/* Запоминаем номер первого байта массива, следующего после изменённого, т.е. 40, если. nChange=2 Заметим, что в этом простом примере это можно не делать.*/

fgetpos(arf,&p); // или p=ftell(arf);

// Переходим на начало файла для дальнейшего его чтения

rewind(arf);

fread(a,sizeof(a),1,lf);

while (!feof(lf))

{ printf("\n"); for(j=0;j<m;j++) printf("%d ",a[j]);

fread(a,sizeof(a),1,lf);

}

/* Чтение файла, а, значит, и переход в его начало можно здесь опустить, так как в предыдущем пункте 4.1 была составлена функция для чтения. Её можно вызвать при необходимости. */

fclose(lf);

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: