Бинарные файлы
Перенаправление стандартного ввода-вывода
Текстовые файлы
Для работы с текстовыми файлами удобнее всего пользоваться функциями fprintf(), fscanf(), fgets() и fputs().
Создание текстовых результирующих файлов обычно необходимо для оформления отчетов по лабораторным и курсовым работам.
Рассмотрим пример создания текстового файла:
#include<stdio.h>
void main(void) {
FILE *f1;
int a=2, b=3;
If(!(f1=fopen(“d:\\work\\f_rez.txt”,”w+t”)))
{ // Эапись (!f1) равносильна (f1==NULL)
puts(“Файл не создан!”);
return;
}
fprintf(f1,” Файл результатов \n”);
fprintf(f1,” %d плюс %d = %d\n”,a,b,a+b);
fclose(f1);
}
Просмотрев содержимое файла, можно убедиться, что данные в нем располагаются точно так же, как на экране при использовании функции printf().
В консольном режиме существует понятие стандартных файловых потоков: stdin - ввод (по умолчанию - клавиатура), stdout - вывод (по умолчанию - консоль), stderr - вывод сообщений об ошибках (по умолчанию - консоль).
Эти потоки имеют тип FILE *, и их удобство в том, что их можно перенаправлять функцией freopen(), например:
|
|
freopen("results.txt", "w", stdout);
Теперь все результаты работы программы будут выводиться в файл results.txt так же, как они выводились бы на экран консоли.
Замечание. В случае перенаправления stdin не рекомендуется при вводе пользоваться fflush(), т.к. с файлом она работает иначе, чем с клавиатурой, из-за различной буферизации их в компьютере (см. также тему «Функции ввода-вывода»). Вместо нее надо использовать другие средства. Например, если после scanf() функция gets() вводит пустую строку, можно дважды вызывать gets().
При чтении-записи бинарных (двоичных) файлов удобнее всего пользоваться функциями, выполняющими блоковый ввод-вывод: fread () и fwrite ().
Пример: Сохранить, а затем прочесть из файла значения целых переменных i и j.
int i,j;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
FILE *f=fopen("my.dat", "wb");
fwrite(&i, sizeof(int), 1, f);
fwrite(&j, sizeof(int), 1, f);
fclose(f);
}
//--------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
FILE *g=fopen("my.dat", "rb");
fread(&i, sizeof(int), 1, g);
fread(&j, sizeof(int), 1, g);
fclose(g);
}
Рассмотрим некоторые функции, которые могут пригодиться для работы с файлами (они работают с любыми файлами, но чаще применяются к бинарным):
int fileno(FILE *f) | – возвращает значение дескриптора файла f - fd (число, определяющее номер файла); |
long filelength(int fd) | – возвращает длину в байтах файла, имеющего номер (дескриптор) fd; Часто поэтому применяется вместе с fileno(); |
int chsize(int fd, long pos) | – выполняет изменение размера файла, имеющего номер fd, конец файла устанавливается после байта с номером pos; |
intfseek(FILE *f, long size, int kod) | – выполняет смещение указателя позиции в файле f на size байт в направлении признака kod: 0 - от начала файла; 1 - от текущей позиции указателя; 2 - от конца файла. Заметим, что при kod>0 может быть size<0. |
long ftell(FILE *f) | – возвращает значение указателя позиции в файле (-1 – ошибка); |
intfgetpos(FILE *f, long *pos) | – определяет значение текущей позиции pos файла f, возвращает 0 при успешном завершении. |
Функция fseek может многократно ускорять и упрощать работу с файлами, т.к. она позволяет начать чтение/запись в файле сразу с требуемого места. Подобный способ работы называется прямым доступом к файлу, в отличие от обычного, последовательного доступа, когда информация читается последовательно, от начала к концу. Прямой доступ широко применяется для баз данных. Однако прямой доступ применяется в основном для бинарных файлов (в текстовых файлах трудно вычислить значение нужной позиции в байтах, т.к. разные строки могут иметь разную длину).
|
|
При расчете смещения для fseek может пригодиться операция sizeof.
Замечание. Из-за буферизации (см. выше) непосредственно после операции записи нельзя выполнять чтение, и наоборот (не считая случая, когда при чтении достигнут конец файла, что гарантирует исчерпание буфера). Либо файл должен быть переоткрыт заново, либо указатель позиции должен быть установлен в заданное место с помощью fseek.