Слайд 2План
Понятие файла
Потоковый ввод/вывод
Двоичный (бинарный) режим обмена с файлами
Строковый обмен с
файлами
Режим форматного обмена с файлами
Позиционирование в потоке
Ввод-вывод нижнего уровня
Слайд 3ПОНЯТИЕ ФАЙЛА
отсутствие заранее спланированных структур файлов
файлы рассматриваются как неструктурированная
последовательность байтов
три уровня ввода-вывода:
потоковый ввод-вывод,
ввод-вывод нижнего уровня
и
ввод-вывод для консоли и портов.
Слайд 4ПОТОКОВЫЙ ВВОД-ВЫВОД
На уровне потокового ввода-вывода обмен данными производится побайтно.
устройства
внешней памяти, строго говоря, являются устройствами поблочного обмена, т.е. за
одно обращение к устройству производится считывание или запись фиксированной порции данных.
блоки в 512 байт или 1024 байта
поток - это файл вместе с предоставляемыми средствами буферизации
Слайд 5При работе с потоком можно производить следующие действия:
открывать и закрывать
потоки (связывать указатели на потоки с конкретными файлами);
вводить и выводить:
символ, строку, форматированные данные, порцию данных произвольной длины;
анализировать ошибки потокового ввода-вывода и условие достижения конца потока (конца файла);
управлять буферизацией потока и размером буфера;
получать и устанавливать указатель (индикатор) текущей позиции в потоке.
#include
содержит прототипы функций ввода-вывода, а также определения констант, типов и структур, необходимых для работы функций обмена с потоком.
Слайд 6Открытие и закрытие потока
В структуре FILE содержатся компоненты, с помощью
которых ведется работа с потоком, в частности: указатель на буфер,
указатель (индикатор) текущей позиции в потоке и другая информация.
#include
FILE *fp;
функции открытия потока:
fp = fopen (имя файла, режим открытия);
Слайд 7Параметры имяфайла и режим открытия являются указателями на массивы символов
fp = fopen("t.txt", "r");
шесть режимов
"w"
"r"
"а"
"w+"
"r+"
"а+"
Поток можно открыть в текстовом либо двоичном (бинарном) режиме
В текстовом режиме прочитанная из потока комбинация символов CR (значение 13) и LF (значение 10), то есть управляющие коды "возврат каретки" и "перевод строки", преобразуется в один символ новой строки '\n' (значение 10, совпадающее с LF).
двоичную информацию
"r+b" или "wb".
Слайд 8Ошибки при открытии потока :
указанный файл, связанный с потоком,
не найден (для режима "чтение");
диск заполнен или диск защищен
от записи и т.п
при выполнении функции fopen() происходит выделение динамической памяти. При ее отсутствии устанавливается признак ошибки "Not enough memory" (недостаточно памяти). В перечисленных случаях указатель на поток приобретает значение NULL.
if ((fp = fopen("t.txt", "w")) == NULL) {
perror("ошибка при открытии файла t.txt \n") ;
exit(0);
}
int fclose (указатель на поток );
Слайд 9Работа с файлами на диске
fgetc(), getc() - ввод (чтение) одного
символа из файла;
fputc(), putc() - запись одного символа в файл;
fprintf(
) - форматированный вывод в файл;
fscanf( ) - форматированный ввод (чтение) из файла;
fgets() - ввод (чтение) строки из файла;
fputs() - запись строки в файл.
Слайд 10ДВОИЧНЫЙ (БИНАРНЫЙ) РЕЖИМ ОБМЕНА С ФАЙЛАМИ
1 способ. Двоичный режим обмена
организуется с помощью функций getc() и putc()
с= getc(fp); putc(c, fp);
где
fp - указатель на поток;
с - переменная типа int для приема очередного символа из файла или для записи ее значения в файл.
Прототипы функции:
int getc ( FILE *stream );
int putc (int c, FILE *stream );
Слайд 11Программа ввода читает символы с клавиатуры и записывает их в
файл.
#include
int main () {
FILE *fp;
/* Указатель на поток */
char с;
/* Восьмеричный код "Возврат каретки": */
const char CR='\015';
/* Восьмеричный код "Перевод строки": */
const char LF = ' \012•;
char fname[20] ; /* Массив для имени файла */
/* Запрос имени файла: */
puts("введите имя файла: \т");
gets(fname);
/* Открыть файл для записи: */
Слайд 13программа читает поток символов из ранее созданного файла и выводит
его на экран дисплея:
#include
int main () {
FILE *fp;
/* Указатель на поток */
char с;
char fname[20]; /* Массив для имени файла */
/* Запрос имени файла: */
puts ( "введите имя файла: \n "); gets(fname);
/* Открыть файл для чтения: */
if ( ( fp = fopen ( fname,"r" ) ) = = NULL) {
perror(fname);
return 1; }
/* Цикл чтения из файла и вывода символов на экран: */
while ((с = getc(fp)) != EOF)
putchar(с) ;
fclose(fp); /* Закрыть файл */
return 0; }
Слайд 14СТРОКОВЫЙ ОБМЕН С ФАЙЛАМИ
stdio.h имеют следующий вид:
int fputs (const char
*s, FILE *stream);
char * fgets (char *s, int n,
FILE * stream);
Функция fputs() записывает ограниченную символом '\0' строку (на которую указывает s) в файл, определенный указателем stream на поток, и возвращает неотрицательное целое. При ошибках функция возвращает EOF. Символ '\0' в файл не переносится, и символ '\n' не записывается в конце строки вместо '\0'.
Слайд 15Функция fgets() читает из определенного указателем stream файла не более
(n-1) символов и записывает их в строку, на которую указывает
s. Функция прекращает чтение, как только прочтет (n-1) символов или встретит символ новой строки '\n', который переносится в строку s.
Слайд 16>copyfile.exe f1.dat f2.txt
#include
main (int argc,
char *argv[ ]) {
char cc[256];/* Массив для обмена с
файлами */
FILE *f1, *f2; /* Указатели на потоки */
if (argc == 3) /* Проверка командной строки */ {
printf("\n Формат вызова программы: ");
printf("\n copyfile.exe"
printf("\n файл-источник файл-приемник");
return 1; }
if ((f1 = fopen(argv[1], "г")) == NULL) /* Открытие входного файла */ {
perror(argv[l]); return 1; }
if ((f2 = fopen(argv[2], "w")) == NULL) /* Открытие выходного файла */ {
perror(argv[2]); return 1; }
while (fgets(cc, 256, f1) != NULL)
fputs(cc, f2);
fclose(fl); fclose(f2);
return 0; }
Слайд 17РЕЖИМ ФОРМАТНОГО ОБМЕНА С ФАЙЛАМИ
int fprintf ( указатель напоток, форматная-строка,
список-переменных);
int fscanf (указатель_на_поток, форматная строка, список адресов переменных);
#include
int
main() {
FILE *fp; /* Указатель на поток */
int n;
if ((fp = fopen("int.dat","w")) == NULL) {
perror("int.dat");
return 1; } .
for (n=1; n<10; n++)
fprintf(fp, "%d %d\n", n, n*n);
fclose(fp);
return 0;}
Слайд 18#include
int main() {
FILE *fp; /* Указатель
на поток */
int n, nn, i ;
if ((fp = fopen("int.dat","r")) == NULL) {
perror("int.dat"); return 1;
}
for (i=1; i<11; i++) {
fscanf(fp, "%d %d", &n, &nn) ;
printf(" %d %d \n",n, nn);
}
fclose(fp);
return 0;
}
Слайд 19#include
#include
void main(void) {
int m[10][10],i=0,j=0;
FILE *f;
clrscr();
f=fopen("C:\\1.txt","r");
while(!feof(f)) {
fscanf(f,"%d\n",&m[i][j]);
printf("%d\n",m[i][j]);
i++;
j++;
}
getch();
fclose(f);
}
Слайд 20ПОЗИЦИОНИРОВАНИЕ В ПОТОКЕ
int fseek (указатель на поток, смещение, начало отсчета);
Смещение
задается переменной или выражением типа long
SEEK_SET (имеет значение 0)
- начало файла;
SEEK_CUR (имеет значение 1) - текущая позиция;
SEEK_END (имеет значение 2) - конец файла.
Функция fseek() возвращает 0, если перемещение в потоке (файле) выполнено успешно
Перемещение к началу потока (файла) из произвольной позиции:
fseek(fp, 0L, SEEK_SET);
Перемещение к концу потока (файла) из произвольной позиции:
fseek(fp, 0L, SEEK_END);
Слайд 21struct str{…
} st;
ffseek(fp, -(long)sizeof(st), SEEK_CUR);
long ftell(FILE *)
- получить значение указателя
текущей позиции в потоке;
void rewind(FILE *)
- установить указатель текущей
позиции в потоке на начало потока.
Позиционирование в текстовом файле
Слайд 22ДВОИЧНЫЕ ФАЙЛЫ ПРОИЗВОЛЬНОГО ДОСТУПА (2 СПОСОБ БИНАРНОГО ОБМЕНА)
Двоичный файл -
неограниченный массив байтов.
- двоичный файл представляет собой неограниченный массив
байтов внешней памяти;
- формы представления данных во внутренней памяти компьютера (переменные) и в двоичном файле полностью идентичны;
- программа имеет возможность при помощи функций ввода/вывода копировать любую область файла в любую область памяти без преобразования («байт в байт»). Таким образом, можно разместить в любом месте файла любую переменную из памяти программы в том виде, в каком она присутствует в памяти, и прочитать ее обратно;
Слайд 23- в отличие от памяти программы, которая распределяется частично транслятором
(обычные переменные), частично библиотечными функциями (динамические переменные), память в файле
распределяется самой программой. Только она определяет способ размещения данных, метод доступа к ним и несет ответственность за корректность этого размещения.
Слайд 24Функции стандартной библиотеки для работы с двоичным файлом.
// Открыть
существующий как двоичный для чтения и записи
FILE *fd; fd
= fopen(“a.dat","rb+wb");
// Создать новый как двоичный для записи и чтения
fd = fopen("a.dat","wb+");
Текущей позицией называется номер байта, начиная с которого производится очередная операция чтения/записи, что интерпретируется как адрес переменной в файле. Другой, часто используемый, термин - смещение.
Слайд 25Функции fread и fwrite используются для перенесения данных из файла
в память программы (чтение) и обратно (запись).
int fread
(void *buf, int size, int nrec, FILE *fd);
int fwrite (void *buf, int size, int nrec, FILE *fd);
Слайд 26// Записать в файл переменную
// типа long, начиная с
позиции 20
long a=0x1256;
fseek (fd, 20L, SEEK_SET);
fwrite ((void*)&a,
sizeof(long),1 ,fd);
// Добавить в файл переменную
// типа man
struct man b;
fseek (fd,0L,SEEK_END);
fwrite ((void*)&b, sizeof b,1,fd);
// Прочитать с начала файла
// динамический массив из п переменных типа double
double *pd = new double[n];
fseek(fd,OL,SEEK_SET);
fread ((void *)pd, sizeof (double), n,fd);
Слайд 27Способы распределения памяти
int a;
long pos;
fseek(fd,0L,SEEK_END);
pos=ftell(fd);
fwrite((void*)&a, sizeof(int),1 ,fd);
обновление (UpDate).
а++;
fseek(fd,pos,SEEK_SET);
fwrite((void*)&a,
sizeof(int), 1 ,fd);
Слайд 28Доступ к данным в файле происходит на физическом уровне, то
есть по адресу.
Существуют два способа получения адреса:
адрес вычисляется, исходя
из количества и размерности переменных. Простейший случай - файл записей фиксированной длины (массив), адрес записи вычисляется как произведение номера записи на ее размерность;
адрес содержится в другой части структуры данных, то есть структура данных использует файловые указатели.
Слайд 29ВВОД-ВЫВОД НИЖНЕГО УРОВНЯ
При низкоуровневом открытии файла с ним связывается не
указатель файла (потока), а дескриптор (handle) файла.
Дескриптор является целым
значением, характеризующим размещение информации об открытии файла во внутренних таблицах операционной системы. Дескриптор файла используется при последующих операциях с файлом.
Слайд 30основные функции ввода-вывода нижнего уровня:
ореn( )/close( ) - открыть /
закрыть файл;
creat() - создать файл;
read( )/write() - читать / писать
данные;
sopen() - открыть файл в режиме разделения, т.е. для одновременного доступа со стороны нескольких процессов (работающих программ);
eof() - проверить достижение конца файла;
lseek() - изменить текущую позицию в файле;
tell() - получить значение текущей позиции в файле.
Слайд 31Постраничный просмотр текста.
// Вывод текста с заданной страницы
FILE *fd;
char
name[30] = "d310.txt" , str[80];
int i,n,NP; // Количество страниц в файле
long
POS[100]; // Массив указателей начала страниц в файле
void main() {
if ((fd=fopen(name,"r"))==NULL) return;
for (NP=0; NP<100; NP++){ // Просмотр страниц файла
POS[NP]=ftell(fd); // Запомнить начало страницы
for (i=0; i<20; i++) // Чтение строк страницы
if (fgets(str,80,fd)==NULL) break; // Конец файла - выход из цикла
if (i < 20) break; // Неполная страница - выход
}
Слайд 32while(1){
printf("page number:");
scanf("%d",&n);
if ((n >= NP) || (n
fseek(fd,POS[n],SEEK_SET); // Позиционироваться на страницу
for (i=0; i<20; i++) { // Повторное чтение страницы
if (fgets(str,80,fd) = = NULL) break;
puts(str);
}
}
}