Файлы. Работа с файлами в языке с. Файловый ввод-вывод  в языке С++

Арендный блок
Лекция №8

9. ФАЙЛЫ

9.1. РАБОТА С ФАЙЛАМИ В ЯЗЫКЕ С

Открытие и закрытие файла

ФАЙЛЫ. РАБОТА С ФАЙЛАМИ В ЯЗЫКЕ С.

Открытие файла для ввода-вывода через поток выполняет функция fopen().

      #include<stdio.h>

     FILE*fopen(const char*filename,const char*mode)

   Возвращает указатель на переменную типа FILE, описывающий открытый поток файлового ввода-вывода. Если невозможно открыть файл, функция возвращает NULL-указатель. Переменная filename-указатель на ASCIIZ-строку символов, задающую спецификацию открытого файла. Если не специфицируется буква накопителя, используется накопитель по умолчанию. Если не задан абсолютный маршрут, в качестве начального директория используется текущая рабочая директория выбранного накопителя. Переменная mode-указатель на ASCIIZ-строку символов, задающую режим открытия файла. Образуется комбинацией символов, приведенных в табл.3.1.

Табл.1. Символы задания режима открытия потока ввода-вывода

ЗнакФункцияr Файл открывается только для чтения. Так может быть открыт лишь уже существующий файл. Если файл с заданной спецификацией не существует, fopen() возвращает NULL. При успешном открытии указатель записи-чтения файла устанавливается в 0. w  Файл открывается только для записи с усечением. Если файл не существует, он создается в заданном параметром filename директории. Созданный файл имеет атрибут архивного файла. Если создать файл не удается, функция возвращает NULL. Если файл существует, но имеет атрибут "только читаемый", возвращается NULL. При успешном открытии указатель записи-чтения файла устанавливается в 0. По этой причине возможно переопределение содержимого существующего файла, если перед доступом к файлу не выполняется принудительная установка указателя. Если все предыдущее содержимое должно быть сохранено, можно либо сразу после открытия выполнить перемотку указателя на конец файла (см. далее), либо открыть файл в режиме пополнения содержимого – режиме "а". Попытка чтения из файла завершается возвратом ошибки функцией чтения. После закрытия файл имеет всегда "новый" размер, соответствующий текущему положению указателя записи-чтения. Поэтому открытие существующего файла и его немедленное закрытие усекают файл до нулевой длины.a  Файл открывается для пополнения. Все то же самое, что и для режима "w", но после открытия файла указатель записи-чтения устанавливается на позицию конца файла. В результате запись в файл происходит с сохранением предыдущего содержимого.r+  Файл открывается для обновления. Он доступен для чтения и записи, но после закрытия не происходит усечение файла: размер файла остается прежним, если текущий указатель записи-чтения файла состоит "левее" прежнего положения EOF. Сразу после открытия файла указатель устанавливается на начало файла.w+  Файл открывается для обновления. Он доступен для чтения и записи, после закрытия существующий файл усекается. Если открываемый файл не существует, он создается в директории, задаваемом спецификацией файла. Сразу после открытия файла указатель записи-чтения файла устанавливается на начало файла.  Файл открывается для обновления. Он доступен для чтения и записи, но после закрытия не происходит усечения файла. Сразу после открытия файла указатель записи-чтения устанавливается на позицию EOF.a+  Файл открывается для обновления. Он доступен для чтения и записи, но после закрытия существующий файл не усекается. Сразу после открытия файла указатель записи-чтения устанавливается на позицию EOF.b  Файл открывается в двоичном режиме (см.3.1). Специализируется после r, w, a, r+, w+, a+, например "a+b". Для повышения мобильности программного кода предпочтительнее использовать управление двоичным или текстовым режимом через переменную _fmode, так как реализации Си для других ОС могут и не содержать параметров b или t при открытии файла.t  Файл открывается в текстовом режиме (см.3.1). Специализируется после r, w, a, r+, w+, a+, например “rt”.

   Если данный файл открывается или создается в текстовом режиме, вы можете приписать символ t к значению параметра type (rt, w+t, и т.д.); аналогично, для спецификации бинарного режима вы можете к значению параметра type добавить символ b (wb, a+b, и т.д.).

 Если в параметре type отсутствуют символы t или b, режим будет определяться глобальной переменной _fmode. Если переменная _fmode имеет значение O_BINARY, файлы будут открываться в бинарном режиме, иначе, если _fmode имеет значение O_TEXT, файлы открываются в текстовом режиме. Данные константы O_... определены в файле fcntl.h.

 При открытии файла в режиме обновления (UPDATE), над результирующим потоком stream могут быть выполнены как операции ввода, так и вывода. Тем не менее вывод не может следовать непосредственно за вводом без вмешательства функций fseek или rewind. Также ввод, без применения функций fseek, rewind не может непосредственно следовать за выводом или вводом, который встречает конец файла (EOF).

Пример:

#include <stdio.h>

int main(void)

{

   FILE *in, *out;

   if((in = fopen("\\AUTOEXEC.BAT","rt"))==NULL)

   {

     fprintf(stderr, "Не могу открыть файл \n");

     return(1);

   }

   if((out = fopen("\\AUTOEXEC.BAK","wt"))==NULL)

   {

     fprintf(stderr, "Не могу открыть выходной файл \n");

     return(1);

   }

while(!feof(in))

    fputc(fgetc(in), out);

fclose(in);

fclose(out);

return 0;

}

Функция fclose

Функция

   #include <stdio.h>

     int fclose (FILE * stream);

закрывает указанный поток stream. Все буфера, связанные с потоком stream, перед закрытием сбрасываются. Буфера, размещенные системой, освобождаются во время процесса закрытия. Буфера, назначенные функциями setbuf или setvbuf, не освобождаются автоматически. (Однако, если в качестве указателя, функции setvbuf передать 0, то он будет освобожден при закрытии потока.)

Функция fclose при успешном завершении возвращает 0. Если были обнаружены какие-либо ошибки, функция  fclose возвращает значение EOF.

Пример:

#include<string.h>

#include<stdio.h>

int main(void)

{

   FILE *fp;

   char buf[11] = "0123456789";

   /* создать файл содержащий 10 байт */

   fp = fopen("DUMMY.FIL","w");

   if(fp)

   {

fwrite(&buf,strlen(buf),1,fp);

 /* закрыть файл */

fclose(fp);

   }

   else

   {

printf("Ошибка, при открытии файла\n");

   }

   return 0;

}

Функция fcloseall

Функция

           #include <stdio.h>

           int fcloseall (void)

закрывает все открытые потоки ввода-вывода. за исключением stdin, stdout, stderr, stdaux, stdprn. Возвращает общее число потоков, закрытых функцией, либо EOF, если обнаружены какие-либо ошибки при закрытии файлов.

Пример:

#include<stdio.h>

int main(void)

{

   FILE *fp1,*fp2;

   int streams_closed;

   /* открыть два потока */

   fp1 = fopen("DUMMY.ONE","w");

   fp2 = fopen("DUMMY.TWO","w");

   /* закрыть открытые потоки */

   streams_closed = fcloseall();

   if(streams_closed == EOF)

      /* вывести сообщение об ошибке */

      perror(" Ошибка ");

   else

      /* вывести результат работы функции */

      printf("Было закрыто %d потока\n",streams_closed);

   return 0;

}

Функция feof

Функция

      #include<stdio.h>

 int feof(FILE * stream);

является макрокомандой, которая производит проверку данного потока stream на признак конца файла (EOF). Если признак получил значение хотя бы один раз, то операции чтения файла сохраняют это значение до тех пор, пока не будет вызвана функция rewind или файл не будет закрыт.  Признак конца файла сбрасывается при каждой операции ввода.

 Функция feof возвращает ненулевое значение, если  при последней операции ввода потока stream был обнаружен конец файла, и 0 в противном случае.

Пример:

#include <stdio.h>

int main(void)

{

   FILE *stream;

   char ch;

   /* открыть файл для чтения */

   stream = fopen("DUMMY.FIL", "r");

   /* ввести из файла символ */

   ch = fgetc(stream);

   /* конец файла? */

   if(feof(stream))

      printf("Конец файла\n");

   /* закрыть файл */

   fclose(stream);

   return 0;

}

Функция fscanf

Функция

    #include <stdio.h>

     int fscanf(FILE * stream, char * format[,   adress,...]);

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

  Описание спецификаций формата приведено в описании функции scanf.

  Функция fscanf завершает сканирование отдельного поля при появлении пробела, являющегося разделителем, или  при вводе поля, для которого указана ширина. Эти случаи обсуждаются в описании функции scanf.

  Функция fscanf возвращает количество успешно прочитанных, преобразованных и запомненных входных   полей; возвращаемое значение не включает в себя прочитанные поля, которые не были сохранены.

   Если fscanf делает попытку чтения в конце файла,  то возвращается EOF. Если не было записано ни одного поля, возвращается значение 0.

Пример:

#include<stdlib.h>

#include<stdio.h>

int main(void)

 {

   int i;

   printf("Введите целое число:");

   /* ввести из стандартного потока stdout целое число */

   if(fscanf(stdin,"%d",&i))

     printf("Целое равно:%d\n",i);

   else

    {

     fprintf(stderr,"Ошибка чтения целого\n");

     exit(1);

    }

   return 0;

}

Функция freopen

Функция

           #include <stdio.h>

           FILE*freopen (const char*filename, const char*mode, FILE*stream)

закрывает поток, на описание которого указывает stream, а затем открывает файл, на спецификацию которого указывает ASCIIZ-строка filename. Режим открытия файла задает ASCIIZ- строка mode. Символы, формирующие режим, приведены в табл.3.1. В случае успеха функция возвращает указатель на описание открытого потока, которое будет совпадать с stream. В противном случае функция возвращает NULL. Повторное открытие того же самого файла изменяет права доступа, очищает внутренние буферы и позиционирует указатель записи-чтения либо на начало файла (r, w, r+, w+), либо на его конец (а, а+). Если файлы разные, переоткрытие приводит к переадресации файлового ввода-вывода. Эта функция обычно применяется для переадресации  предоткрытых  потоков stdin, stdout, stderr, stdaux, stdprn в файлы, определяемые пользователем.

Функция ftmpfile

Функция

          #include<stdio.h>

          FILE*tmpfile (void)

Создает и открывает временный файл в текущей директории текущего накопителя для потокового ввода-вывода. Файл открывается с правами “w+b”. В случае успеха функция возвращает указатель на начало описания открытого потока. В противном случае возвращается NULL. Отсутствует возможность определить имя созданного файла. После завершения программы или закрытия файла он автоматически удаляется. Функция используется тогда, когда программе необходимо временно переместить промежуточные данные на диск.

Пример тестовой программы:

          /*L3_1.C*/

          #include<stdio.h>

          #include<process.h>

          #include<errno.h>

          void file_prt(FILE*);

          void main(int argc, char**argv)

        { FILE*fptr;

           if(argc<3)/* все ли аргументы заданы?*/

             { printf(“\аНеправильно заданы аргументы. “\

                         “Использование программы:\n”\

                         “L3_1[d:][маршрут_директория ] имя_файла”\

                         “[.расширение] режим_открытия\n”);

              exit(1); }

            if((fptr=fopen(argv[1], argv[2]))!=NULL)

               { file_prt(fptr); /*распечатывает поля fptr*/

                  fclose(fptr); } /*открытый файл закрывается*/

            else perror(“\aОшибка открытия файла”);

           }

            /*Внутренняя функция L3_1.C. Распечатывает поля переменной, описывающей        открытый поток, на которую указывает fptr.*/

           void file_prt(FILE*fptr)       

           { printf(“ Поля переменной по шаблону FILE после открытия\n\n”\

              “level=%#06x flags=%#06x fd   =%#06x”\

              “hold=%#06x bsize=%#06x\nbuffer=%#06x”\

              “curp=%#06x istemp=%#06x token=%#06x\n” ,

               fptr->level,fptr->flags,fptr->fd,

               fptr->hold,fptr->bsize,fptr->buffer,

               fptr->curp,fptr->istemp,fptr->token);

/* Вывод символического представления флагов*/

               printf(“\nСимволическое представление флагов открытия\n”\

                          “  (Да=1, Нет=0) \n”\

“_F_READ %d Файл открыт для чтения\n”\

“_F_WRITE %d Файл открыт для записи\n”\

“_F_BUF %d Файл имеет выделенный динамически буфер данных\n”\

“_F_LBUF %d Построчно буферизуемый файл\n”\

“_F_ERR %d Индикатор наличия ошибки при выполнении файлового доступа\n”\

“_F_EOF %d Индикатор наступления условия конца файла\n”\

“_F_BIN %d Признак открытия файла в двоичном режиме\n”\

“_F_IN %d Осуществляется чтение(ввод) данных из файла\n”\

“_F_OUT %d Осуществляется запись(вывод) данных в файла\n”\

“_F_TERM %d Файл является терминалом\n”,

             fptr->flags&_F_READ,( fptr->flags&_F_WRIT)>>1,

             (fptr->flags&_F_BUF)>>2,( fptr->flags&_F_LBUF)>>3,

             (fptr->flags&_F_ERR)>>4,( fptr->flags&_F_EOF)>>5,

             (fptr->flags&_F_BIN)>>6,( fptr->flags&_F_IN)>>7,

             (fptr->flags&_F_OUT)>>8,( fptr->flags&_F_TERM)>>9);

}

Функция fdopen

Функция

   #include<stdio.h>

   FILE * fdopen(int handle, char * type);

связывает поток с дескриптором, полученным функциями creat, dup, dup2 или open. Тип потока должен совпадать с режимом, в котором был открыт handle(см. таблицу 1).

 При успешном завершении fdopen  возвращает значение заново открытый поток stream. В случае ошибки, функция возвращают ноль (NULL).

Пример:

#include<sys\stat.h>

#include <stdio.h>

#include <fcntl.h>

#include<io.h>

int main(void)

{

   int handle;

   FILE *stream;

   /* открыть файл */

   handle = open("DUMMY.FIL", O_CREAT, S_IREAD|S_IWRITE);

   /* теперь преобразуем его в поток */

   stream = fdopen(handle, "w");

   if (stream == NULL)

      printf("Ошибка fdopen\n");

   else {

      fprintf(stream, "Hello, world\n");

      fclose(stream);

   }

   return 0;

 }

Функция eof

Функция     

    #include<io.h>

      int eof(int handle);

 определяет, достигнут ли конец файла, связанного с дескриптором handle.

Если текущая позиция является концом файла, функция eof возвращает значение 1; в противном случае значение 0. При возникновении ошибки возвращается  значение -1, и глобальная переменная errno получает значение: EBADF - Неверный номер файла.

Пример:

#include<process.h>

#include<string.h>

#include<stdio.h>

#include<io.h>

int main(void)

{

   FILE *temp_file;

   int handle;

   char msg[] = "Тестовый пример";

   char ch;

   /* создать уникальный временный файл */

   if((temp_file=tmpfile()) == NULL)

   {

      perror("Открытие файла:");

      exit(1);

   }

   /* получить дескриптор данного файла */

   handle = fileno(temp_file);

   /* записать в файл данные */

   write(handle,msg,strlen(msg));

   /* переместить указатель в начало файла */

   lseek(handle,0l,SEEK_SET);

   /* считывать данные до появления конца файла */

   do

   {

      read(handle,&ch,1);

      printf("%c",ch);

   } while(!eof(handle);

   /* закрыть временный файл */

   fclose(temp_file);

   return 0;

}

       Функция ferror

 Функция     

    #include<stdio.h>

int ferror(FILE * stream);

является макрокомандой, которая проверяет данный поток stream на ошибочную операцию записи или чтения. Если установлен признак ошибки потока stream, он сохраняет его до вызова функций clearerr или rewind или до момента закрытия потока.

   Функция ferror возвращает ненулевое значение, если в потоке stream была обнаружена ошибка.

Пример:

#include <stdio.h>

int main(void)

{

   FILE *stream;

   char ch;

   /* открыть файл для записи */

   stream = fopen("DUMMY.FIL", "w");

   /* справоцировать ошибку */

   ch = fgetc(stream);

   /* конец файла? */

   if(ferror(stream))

   {

      /* вывести сообщение об ошибке */

      printf("Ошибка чтения\n");

      /* сбросить признак ошибки */

      clearerr(stream);

   }

   fclose(stream);

   return 0;

}

       Функция fflush

 Функция 

    #include<stdio.h>

int fflush(FILE * stream);

записывает в файл содержимое буфера, связанного с потоком stream, если он был открыт на вывод. Функция fflush не оказывает влияния на не буферизованные потоки.

 В случае успешного завершения возвращает 0. При ошибке возвращает EOF.

Пример:

#include<string.h>

#include<stdio.h>

#include<conio.h>

#include<io.h>

void flush(FILE *stream);

int main(void)

 {

   FILE *stream;

   char msg[] = "Тестовый пример";

   /* создать файл */

   stream = fopen("DUMMY.FIL","w");

   /* записать в файл данные */

   fwrite(msg,strlen(msg),1,stream);

   clrscr();

   printf("Для сброса потока нажмите любую клавишу ...\n");

   getch();

   /* сбросить данные в файл, без его закрытия */

   flush(stream);

   printf("Содержимое буферов сброшено в файл\n");

   printf("Для завершения нажмите любую клавишу\n");

   getch();

   return 0;

}

void flush(FILE *stream)

 {

   int duphandle;

   /* сбросить внутренние буфера файла */

   fflash(stream);

   /* создать второй дескриптор */

   duphandle = dup(fileno(stream));

   /* закрыть второй дескриптор для сброса буферов DOS */

   close(duphandle);

}

Функция fgetpos

 Функция     

     #include<stdio.h>

 int fgetpos(FILE * stream, fpos_t *pos);

сохраняет позицию указателя файла, связанного с потоком stream, в месте, указываемом pos.  

 Тип fpos_t описывается следующим образом:

    typedef long fpos_t;

 При успешном завершении fgetpos возвращает 0. При ошибке возвращает ненулевое значение и устанавливает errno в EBADF или EINVAL.

Пример:

#include<string.h>

#include<stdio.h>

int main(void)

{

   FILE *stream;

   char string[] = "Тестовый пример";

   fpos_t filepos;

   /* создать файл для его изменения */

   stream = fopen("DUMMY.FIL","w+");

   /* записать в файл данные */

   fwrite(string,strlen(string),1,stream);

   /* сообщить положение указателя */

   fgetpos(stream,&filepos);

   printf("Указатель находится в %ld позиции\n");

   fclose(stream);

   return 0;

 }

        Функция fgets

Функция

   #include<stdio.h>

    char * fgets(char s, int n, FILE *stream);

считывает из потока stream строку символов и помещает ее в s. Ввод завершается после ввода n-1 символа или при вводе символа перехода на следующую строку, смотря что произойдет раньше. В отличие от gets, fgets прекращает ввод строки при  получении символа перехода на следующую строку.

 Нулевой байт добавляется в конец строки для индикации ее конца.

 При успешном завершении возвращает указатель на s, при ошибке или конце файла возвращает NULL.

Пример:

#include<string.h>

#include<stdio.h>

int main(void)

{

   FILE *stream;

   char string[] = "Тестовый пример";

   char msg[20];

   /* создать файл для его изменения */

   stream = fopen("DUMMY.FIL","w+");

   /* записать в файл данные */

   fwrite(string,strlen(string),1,stream);

   /* перейти в начало файла */

   fseek(stream,0,SEEK_SET);

   /* ввести строку из файла */

   fgets(msg,strlen(string)+1,stream);

   /* напечатать строку */

   printf("%s",msg);

   fclose(stream);

   return 0;

 }

     Функция filelength

Функция

  #include<io.h>

   long filelength(int handle);

возвращает длину в байтах файла, соответствующего дескриптору handle.

 При успешном завершении функция filelength возвращает значение типа long- длину файла в байтах. При ошибке функция возвращает значение -1L, и глобальной переменной errno присваивается: EBADF - Неверный номер файла.

Пример:

#include<stdio.h>

#include<io.h>

#include<fcntl.h>

#include<sys\stat.h>

#include<string.h>

int main(void)

{

   int handle;

   char buf[11] = "0123456789";

   /* создать файл из 10 байт */

   handle = open("DUMMY.FIL",O_RDWR|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE);

   write(handle,buf,strlen(buf));

   /* напечатать размер файла */

   printf("Размер файла в байтах : %ld\n",filelength(handle));

   /* закрыть файл */

   close(handle);

   return 0;

}

Функция fileno

 Функция 

   #include<stdio.h>

    int fileno(FILE * stream);

представляет собой макрокоманду, которая  возвращает логический номер файла для заданного потока stream. Если поток stream имеет более одного номера, функция fileno возвращает номер, назначенный данному потоку при первом открытии.

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

Пример:

#include<stdio.h>

int main(void)

{

   FILE *stream;

   int handle;

   /* создать файл */

   stream = fopen("DUMMY.FIL","w");

   /* получить дескриптор файла */

   handle = fileno(stream);

   /* напечатать его */

   printf("Дескриптор файла = %d\n",handle);

   /* закрыть файл */

   fclose(stream);

   return 0;

}

Функция flushall

 Функция 

        #include<stdio.h>

          int flushall(void);

сбрасывает все буфера, связанные   с открытыми входными потоками, и записывает в соответствующие файлы все буфера, относящиеся к открытым выходным потокам. Любые операции чтения,  следующие за функцией flushall, будут читать новые  данные для входных файлов в буферы. Все потоки остаются открытыми.

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

Пример:

#include<stdio.h>

int main(void)

{

   FILE *stream;

   /* создать файл */

   stream = fopen("DUMMY.FIL","w");

   /* сбросить все открытые потоки */

   printf("Сброшено %d потоков\n",flushall());

   /* закрыть файл */

   fclose(stream);

   return 0;

}

Функция dup

Функция

   #include<io.h>

   int dup(int handle);

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

  - тот же самый открываемый файл или устройство;

  - тот же самый адресный указатель файла (то есть изменение одного адресного указателя приводит к изменению другого);

  -тот же самый метод доступа (чтение, запись, чтение/запись).

   Переменная handle получают значения при вызове функций creat,_creat,_open, open, dup, dup2.

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

   При возникновении ошибки глобальная переменная  errno получает одно из следующих значений:

       EMFILE - Слишком много открытых файлов.

       EBADF  - Неверный номер файла.

Пример:

#include<string.h>

#include<stdio.h>

#include<conio.h>

#include<io.h>

void flash(FILE *stream);

int main(void)

 {

   FILE *fp;

   char msg[] = "Тестовый пример";

   /* создание файла */

   fp = fopen("DUMMY.FIL,"w");

   if(fp)

   {

      /* записать в файл данные */

      fwrite(msg,strlen(msg),1,fp);

      clrscr();

      printf(" Для сброса буферов файла на диск нажмите клавишу ");

      getch();

      /* Сброс буферов файда на диск без его закрытия */

      flush(fp);

      printf("Буфера записаны, для завершения нажмите клавишу.");

      getch();

   }

   else

   {

      printf("Ошибка при открытии файла\n");

   }

   return 0;

}

void flash(FILE *stream)

 {

   int duphandle;

   /* сброс внутреннего буфера TC */

   fflash(stream);

   /* сдублировать дескриптор файла */

   duphandle = dup(fileno(stream));

   /* закрыть второй дескриптор, для сброса внутренних буферов DOS */

   close(duphandle);

}

Функция dup2

 Функция     

      #include<io.h>

        int dup2(int oldhandle, int newhandle);

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

  - тот же самый открываемый файл или устройство;

  - тот же самый адресный указатель файла (то есть изменение одного адресного указателя приводит к изменению другого);

   -тот же самый метод доступа (чтение, запись, чтение/запись).

   dup2 создает новый дескриптор со значением newhandle Если файл связанный с дескриптором  newhandle открыт, то при вызове dup2 он закрывается.

   Переменная newhandle и oldhandle - это дескрипторы  файлов, и получают значения при вызове функций  creat,_creat,_open, open, dup, dup2.

   При успешном завершении функция dup2 возвращает 0,  значение     в противном случае функция dup2 возвращает значение -1.

   При возникновении ошибки глобальная переменная errno получает одно из следующих значений:

       EMFILE - Слишком много открытых файлов.

       EBADF  - Неверный номер файла.

Пример:

#include<sys\stat.h>

#include<string.h>

#include<fcntl.h>

#include<io.h>

#include<stdio.h>

#define STDOUT 1

int main(void)

 {

   int fptr,oldstdout;

   char msg[] = "Тестовый пример";

   /* создание файла */

   fptr = open("DUMMY.FIL",O_CREAT|O_RDWR,S_IREAD|S_IWRITE);

   if(fptr)

   {

      /* создать дополнительный дескриптор для stdout */

      oldstdout = dup(STDOUT);

      /* перенаправить стандартный вывод в файл, путем

  дублирования его дескриптора */

      dup2(fptr,STDOUT);

      /* закрыть файл */

      close(fptr);

      /* было перенаправлено в DUMMY.FIL */

      write(STDOUT,msg,strlen(msg));

      /* восстановить исходный дескриптор stdout */

      dup2(oldstdout,STDOUT);

      /* закрыть второй дескриптор stdout */

      close(oldstdout);

   }

   else

   {

      printf("Ошибка при открытии файла. \n");

   }

   return 0;

}

Функции ввода-вывода

#include <stdio.h>int _fgetchar(void);Возвращает символ из файла стандартного ввода.#include <stdio.h>int fgetc(FILE *stream);Возвращает символ из открытого файла, описываемого переменной типа FILE , на которую указывает stream .#include <stdio.h>int getc(FILE *stream);Возвращает символ из открытого файла, описываемого переменной типа FILE , на которую указывает stream . Является макроопределением через функцию _fgetc().#include <stdio.h>int ungetc(int c, FILE *stream);Возвращает символ int c назад в поток stream. Следующая операция чтения из файла stream будет возвращать символ c.

Функция fgetc

Функция

#include <stdio.h>

int fgetc(FILE *stream);

читает отдельный текущий символ из входного потока stream и увеличивает cсоответствующий  указатель  (если  он есть)  для  указания  следующего  считываемого  символа.  

Пример:

#include<string.h>

#include<stdio.h>

#include<conio.h>

int main(void)

{

   FILE *stream;

   char msg[] = "Тестовый пример";

   char ch;

   /* создать файл для его изменения */

   stream = fopen("DUMMY.FIL","w+");

   /* записать в файл данные */

   fwrite(msg,strlen(msg),1,stream);

   /* перейти в начало файла */

   fseek(stream,0,SEEK_SET);

   do

   {

      /* ввести символ из файла */

      ch = fgetc(stream);

      /* вывести символ на экран */

      putch(ch);

   } while(ch!=EOF);

   fclose(stream);

   return 0;

}

Функция getc

Функция

#include <stdio.h>

int getc(FILE *stream);

читает отдельный символ из текущей позиции потока stream и изменяет соответствующий указатель на файл для указания следующего символа.

Пример:

#include <stdio.h>

int main(void)

{

  char ch;

  printf("Input a character:");

  ch = getc(stdin);

  printf("The character input was: '%c'\n", ch);

  return 0;

}

Функция ungetc

Функция

#include <stdio.h>

int ungetc(int c, FILE *stream);

возвращает символ c в заданный поток ввода stream. Stream должен быть буферизованным и открытым для  чтения. Последующая  операция  чтения из stream начинается с символа c. EOF вернуть в поток посредством использования ungetc нельзя.  Эта функция возвращает значение ошибки, если из stream ничего не прочитано   или  если c назад не возвращен. Символы, размещаемые в потоке посредством ungetc, могут быть  уничтожены,  если  функции fseek или rewind вызваны перед считыванием символа из stream.

Пример:

#include <stdio.h>

#include <ctype.h>

int main( void )

{

  int i=0;

  char ch;

  puts("Input an integer followed by a char:");

  while((ch = getchar()) != EOF && isdigit(ch))

     i = 10 * i + ch - 48; /* convert ASCII into int value */

  if (ch != EOF)

     ungetc(ch, stdin);

  printf("i = %d, next char in buffer = %c\n", i, getchar());

  return 0;

}

Функция fputs

 Функция 

       #include <stdio.h>

         int fputs(char * string, FILE * stream);

копирует строку, ограниченную нулевым байтом в поток stream. Она не добавляет в конец  строки символ перехода на новую строку и не выводит нулевой символ.

  При успешном завершении fputs возвращает последний выведенный символ. В противном случае возвращает EOF.

Пример:

#include<stdio.h>

int main(void)

 {

   /* вывести строку в поток */

   fputs("Тестовый пример",stdout);

   return 0;

}

Функция fread

Функция     

        #include <stdio.h>

         size_t fread(void *ptr, size_t size, size_t n, FILE * stream);

считывает n элементов данных, каждый   длиной size байтов, из потока stream в блок с адресной ссылкой ptr.  Общее число вводимых байт равно n x size.

   При успешном завершении функция возвращает количество элементов данных (не байтов),  реально прочитанных.

  В случае достижения конца файла или возникновения ошибки функция fread возвращает short count (возможно 0).

Пример:

#include<string.h>

#include<stdio.h>

int main(void)

{  FILE *stream;

   char msg[] = "Тестовый пример";

   char buf[20];

   if(stream = fopen("DUMMY.FIL","w+")) == NULL)

   { fprintf(stderr,"Не могу открыть файл\n");

      return 1;

   }

   /* вывести в файл данные */

   fwrite(msg,strlen(msg)+1,1,stream);

   /* перейти на начало файла */

   fseek(stream,SEEK_SET,0);

   /* прочитать данные */

   fread(buf,strlen(msg)+1,1,stream);

   printf("%s\n",buf);

   fclose(stream);

   return 0;}

Функция fwrite

 Функция     

   #include <stdio.h>

    size_t fwrite(void * ptr, size_t size, size_t n, FILE * stream);

добавляет n элементов данных, каждое величиной size байт в данный выходной поток. Данные записываются из ptr. Общее число выведенных байт равно n*size.  ptr должен быть объявлен как указатель на некоторый объект.

   При успешном завершении fwrite возвращает число выведенных элементов (не байт). При ошибке она  возвращает меньшее число.

Пример:

#include<stdio.h>

struct mystruct

{

   int i;

   char ch;

}

int main(void)

{

   FILE *stream;

   struct mystruct s;

   /* открыть файл TEST.$$$ */

   if((stream = fopen("TEST.$$$","wb"))==NULL)

   {

      fprintf(stderr,"не могу открыть файл\n");

      return 0;

   }

   s.i = 0;

   s.ch = 'A';

   /* вывод в файл */

   fwrite(&s,sizeof(s),1,stream);

   fclose(stream);

   return 0;

 }

Функция fseek

Функция

   #include <stdio.h>

  int fseek(FILE * stream, long offset,  int fromwhere);

устанавливает адресный указатель файла, соответствующий потоку stream, в новую позицию, которая расположена по смещению offset относительно места в файле, определяемого параметром fromwhere.

   Параметр fromwhere может иметь одно из трех значений 0, 1 или 2, которые представлены тремя символическими константами (определенными в файле  stdio.h), следующим образом:

     ---------------------------------------------------

     Параметр   Размещение в файле

     fromwhere

     --------------------------------------------------

     SEEK_SET (0)   начало файла;

     SEEK_CUR (1)   позиция текущего указателя

      файла;

     SEEK_END (2)   конец файла (EOF);

     --------------------------------------------------

   Функция fseek сбрасывает любой символ, записанный  с помощью функции ungetc.

   Функция fseek используется с операциями ввода/вывода в поток. При работе с дескриптором файла пользуйтесь функцией lseek.

   После этой операции можно производить как ввод, так и вывод в поток.

   Функция fseek возвращает значение 0, если  указатель файла успешно перемещен, и ненулевое  значение в случае неудачного завершения.

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

Пример:

#include <stdio.h>

int main(void)

{

   FILE *stream;

   stream = fopen("MYFILE.TXT", "r");

   print("filesize of MYFILE.TXT is %ld bytes\n",

   filesize(stream));

}

long filesize(FILE *stream);

{

   long curpos,length;

   /* сохранить текущее положение указателя */

   curpos = ftell(stream);

   /* перейти в конец файла */

   fseek(stream, 0L, SEEK_END);

   /* получить текущее положение указателя */

   length = ftell(stream);

   /* восстановить старое положение */

   fseek(stream, curpos, SEEK_SET);

   return(length);

}

Функция fsetpos

 Функция 

#include<stdio.h>

  int fsetpos(FILE *stream, const fpos_t *pos);

устанавливает указатель текущей позиции  файла, связанного с потоком stream в новую позицию, которая определяется значением, получаемым предшествующим вызовом функции fgetpos. fsetpos  также сбрасывает признак конца файла, но не оказывает влияния на символы, помещаемые в поток функцией ungetc. После вызова fsetpos можно производить как операции ввода, так и вывода.

   При успешном завершении fsetpos возвращает 0. При возникновении ошибки она возвращает ненулевое   значение и устанавливает errno не равным 0.

Пример:

#include<stdlib.h>

#include<stdio.h>

void showpos(FILE *stream);

int main(void)

{

   FILE *stream;

   fpos_t filepos;

   /* открыть файл для изменения */

   stream = fopen("DUMMY.FIL","w+");

   /* сохранить текущую позицию указателя */

   fgetpos(stream,&filepos);

   /* записать в файл данные */

   fprintf("stream,"Это тест");

   /* вывести текущую позицию */

   showpos(stream);

   /* установить новую позицию и вывести ее */

  if(fsetpos(stream,&filepos) == 0)

     showpos(stream);

   else

   {

     fpritf(stderr,"Ошибка указателя файла\n");

     exit(1);

   }

   /* закрыть файл */

   fclose(stream);

   return 0;

}

void showpos(FILE *stream)

{

   fpos_t pos;

   /* вывести текущее положение указателя */

   fgetpos(stream,&pos);

   printf("Позиция указателя: %ld\n",pos);

}

Функция fstat

Функция

#include <sys\stat.h>

  int fstat(char * handle, struct stat * buff)

записывает информацию об открытом  файле (или директории), связанным с дескриптором   handle в структуру stat. Aргумент buff адресует  структуру stat (определенную в файле sys\stat.h).

  Структура содержит следующие поля:

   st_mode - битовая маска, дающая информацию о режиме открытия файла;

   st_dev - идентификатор дисковода, на котором был открыт файл, или номер handle, если файл  находится на устройстве;

   st_rdev - так же, как и st_dev;

   st_nlink - присваевается целая константа 1;

   st_size - размер открытого файла в байтах;

   st_atime - ближайшее время открытия файла, во  время которого он был модифицирован;

   st_mtime - так же, как и st_atime;

   st_ctime - так же, как и st_atime.

   Структура stat содержит на три поля больше, чем перечислено выше, они содержат данные, которые под управлением DOS не имеют значения.

   Битовая маска, дающая информацию о режиме открытого файла, содержит следующие биты.

   Один из следующих битов должен быть установлен:

   S_IFCHR - установлен, если параметр handle указывает на устройство (fstat);

   S_IFREG - установлен, если обычный файл определяется параметром handle

   Один или оба следующих бита должны быть установлены:

   S_IWRITE - установлен, если пользователь имеет   разрешение на запись;

   S_IREAD - установлен, если пользователь имеет разрешение на чтение.

   Битовая маска также имеет биты чтения/записи, они устанавливаются в соответствии с режимом доступа к файлу.

   Если информация об открытом файле была успешно получена, функция возвращают значение 0. В случае ошибки (невозможно получить информацию), функция возвращает -1 и присваивают переменной errno:  EBADF - Неверный номер файла.

Пример:

#include<sys\stat.h>

#include<stdio.h>

#include<time.h>

int main(void)

{

   struct stat statbuf;

   FILE *stream;

   /* открыть файл для изменения */

   if((stream = fopen("DUMMY.FIL","w+")) == NULL)

   {

      fprintf(stderr,"Не могу открыть файл.\n");

      return 1;

   }

   fprintf(stream,"Это тест");

   fflush(stream);

   /* получить информацию о файле */

   fstat(fileno(stream),&statbuf);

   /* вывести полученную информацию */

   if(statbuf.st_mode & S_IFCHR)

     printf("Это устройство\n");

   if(statbuf.st_mode & S_IFREG)

     printf("Это файл\n");

   if(statbuf.st_mode & S_IREAD)

     printf("Разрешение на чтение\n");

   if(statbuf.st_mode & S_IWRITE)

     printf("Разрешение на запись");

   printf("Метка диска:%c\n",'A'+statbuf.st_dev);

   printf("Размер в байтах: %ld\n",statbuf.st_size);

   printf("Время последнего открытия: %s\n",

    ctime(&statbuf.st_ctime));

   return 0;

}

Функция ftell

 Функция     

#include <stdio.h>

  long int ftell(FILE *stream);

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

   Значение, возвращаемое ftell, можно в дальнейшем использовать при вызове функции fseek.

   Функция ftell возвращает положение указателя текущей позиции при успешном завершении. При ошибке возвращает-1L, и присваивает переменной errno положительное значение.

Пример:

#include<stdio.h>

int main(void)

{

   FILE *stream;

   stream = fopen("DUMMY.FIL","w+");

   fprintf(stream,"Это тест");

   printf("Указатель файла: %ld\n",ftell(stream));

   return 0;

}

            

9.2. Файловый ввод-вывод  в языке С++

ФункцияНазначениеopenОткрывает файл для чтения/записи, связывая с ним объект класса filebufcloseЗакрывает файлsetbufПередает указанный символьный буфер в распоряжение объекта класса filebufsetmodeЗадает режим доступа к файлу: двоичный (константа filebuf::binary) или текстовый (константа filebuf::text)attachСвязывает указанный открытый файл с объектом класса filebufrdbufВозвращает указатель на объект класса filebuffdВозвращает дескриптор классаis_openПроверяет, открыт ли файл, связанный с потоком

  Для работы с файлами необходимо подключить библиотеку FSTREAM.H (которая в свою очередь подключает файл iostream.h).  

Для чтения данных из файла используется класс ifstream, являющийся потомком класса istream. Для записи данных в файл используется класс ofstream, являющийся потомком класса ostream. Для чтения данных и записи из файла используется класс fstream. Конструктор каждого из этих классов автоматически создает объект класса filebuf, управляющий низкоуровневой работой с файлом, включая поддержку буфера чтения. Функции классов ifstream, ofstream  и iofstream приведены в таблице.

Открытие и закрытие файлов

Для открытия файла можно использовать конструкторы ifstream, ofstream или fstream.

Форма записи:

     ИмяКласса ИмяОбъекта (СтрокаПутьФайл [ , Флаг])

В качестве имени класса должен находиться любой класс, содержащий функции работы с файлами (например, ifstream или ofstream, istream или ostream , или fstream). В качестве ИмяОбъекта любой допустимый идентификатор. СтрокаПутьФайл представляет собой строку, содержащую информацию о месторасположении файла плюс его имя и расширение. При вводе имени файла с клавиатуры с указанием пути и расширения файла, если они требуются,  данные вводятся в обычном виде, например: c:\1\date.txt

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

   fstream f(“c:\\1\\date.txt”,ios::in);

   ifstream fi(“c:\\1\\file1.doc”);

   ofstream fo(“file2.in”);

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

ФлагНазначениеios:: inios::outios::ateios::appios::truncios::nocreateios::noreplaceios::binaryФайл открывается для чтения, его содержимое не очищаетсяФайл открывается для записиПосле создания объекта маркер текущей позиции устанавливается в конец файлаВсе выводимые данные добавляются в конец файлаЕсли файл существует, его содержимое очищается (автоматически устанавливается при открытии файла для записи) Объект не будет создан, если файл не существуетОбъект не будет создан, если файл существуетФайл открывается в двоичном режиме (по умолчанию – в текстовом)

Допускается объединение флагов с помощью операции побитового ИЛИ.

Пример:

   ofstream fo1(“c:\\file1.doc”, ios:: noreplace );

   ofstream fо2(“file2.in”, ios::app| ios::nocreate);

В первом случае делается попытка создать объект fо1 и связать его с файлом file1.doc. Т.к. указан флаг ios:: noreplace,  объект не будет создан, если файл существует, что предохраняет пользователя от нечаянного использования существующего файла для записи в него новых данных.

Во втором случае делается попытка создать объект fо2 и связать его с файлом file2.in. Т.к. указан флаг ios::nocreate,  объект не будет создан, если файл не существует, а если он существует, то после создания объекта данные  будут заносится в конец файла ( при этом исходные данные, хранимые в этом файле не уничтожаются).

   Для обмена данными с файлом можно использовать объект класса fstream.

Например:

  fstream io(“fl.dat”,ios::in|ios::app);

открывает файл для записи и чтения одновременно.

Для закрытия файлов применяется метод close, который опорожняет поток и закрывает закрепленный за потоком файл.

Пример:

#include<iostream.h>

#include<fstream.h>

void main()

{

char name[12];

cout<<”Введите имя файла”<<endl;

cin>>name;

fstream f(name,ios::in);

if(f) cout<<”Файл открыт успешно”;

f.close();

}

Для открытия файлов можно использовать функцию open.

Пример:

#include<iostream.h>

#include<fstream.h>

void main()

{

fstream f;

char name[12];

cout<<”Введите имя файла”<<endl;

cin>>name;

f.open(name,ios::in);

if(f) cout<<”Файл открыт успешно”;

f.close();

}

Параметры, требуемые функцией open, имеют тот же смысл, что и параметры конструкторов потока.

Для записи данных в файл достаточно указать вместо  потока cin имя объекта, связанного с файлом.

Пример:

#include<iostream.h>

void main()

{

char name[30];

cout<<”Введите имя файла:”<<endl;

cin>>name;

fstream f;

f.open(name, ios::out|ios::ate);

f<<”Добавляем запись”;

f.close();

}

Класс istream

Функции управления потоковым вводом сосредоточены в классе istream. С каждым из объектов этого класса и его производных связан объект класса streambuf. Функции класса istream, доступные его потомкам, перечислены в таблице.

ФункцияНазначениеipfxВызывается перед операцией чтения для проверки наличия ошибок в потокеisfxВызывается после каждой операции чтенияgetИзвлекает из потока требуемое число символов; если указан символ-ограничитель, он не извлекаетсяgetlineИзвлекает из потока требуемое число символов; если указан символ-ограничитель, он извлекается, но не сохраняется в буфереreadИзвлекает из потока требуемое число байтов; применяется при работе с двоичными потокамиistream& istream::ignore (int n, int d);Выбрасывает из потока требуемое число символов вплоть до символа-ограничителяint istream::peek();Возвращает значение очередного символа, не извлекая его из потокаint istream::gcount()Определяет число символов, извлеченных из потока во время последней операции чтенияeatwhiteИзвлекает из потока ведущие пробельные символы; аналогичное действие выполняет манипулятор wsistream& istream::putback(char ch);Возвращает в поток символы, извлеченные из него во время последней операции чтенияsyncСинхронизирует внутренний буфер потока с внешним источником символьных данныхistream& istream::seekg (streampos);istream& istream::seekg (streampoff,ios::seek_dir);Перемещает маркер, обозначающий текущую позицию чтения, на требуемую позицию в потокеstreampos istream::tellg()Возвращает позицию маркера чтения

Функции get, getline и read

Следующий  вариант  get позволяет управлять числом извлекаемых символов, их размещением и оконечным символом:

   istream& istream::get(char *buf, int max, int term[='\n']);

    Эта функция считывает символы из входного потока в символьный массив buf до тех пор,  пока не будет считано  max символов,  либо пока не встретится символ,  заданный term, либо пока не встретится конец файла, в зависимости оттого, что произойдет раньше. Завершающий пустой символ добавляется автоматически. По умолчанию терминатором (который не обязательно задавать) является символ новой строки ('\n').  Сам  терминатор  в  массив  buf не считывается и из istream не удаляется. Массив buf должен иметь размер как минимум max символов.

Пример:

#include <iostream.h>

#define NUMCHAR 45

void main()

{ char name[NUMCHAR+1];

 cout<<"Введите ваше имя и фамилию:\n";

 cin.get(name,NUMCHAR);

 cout<<"\nСпасибо,"<<name;

 }

В функции cin.get() первый аргумент – имя переменной, принимающей данные; второй – максимальное число вводимых символов: третий (необязательный) – символ, служащий признаком окончания ввода (по умолчанию используется символ \n). Функция cin.get() считывает все символы в строке, включая пробелы и знаки табуляции, пока не будет прочитано указанное число символов или не встретится символ-ограничитель. Так, например, если в качестве ограничителя используется символ ’*’, то необходимо записать оператор ввода следующим образом

    cin.get(name,NUMCHAR,’*’);

Функция

   istream& istream::getline(char *buf, int max, int term);

считывает символы из входного потока в символьный массив buf до тех пор,  пока не будет считано  max символов,  либо пока не встретится символ,  заданный term, либо пока не встретится конец файла, в зависимости оттого, что произойдет раньше. Завершающий пустой символ добавляется автоматически. По умолчанию терминатором (который не обязательно задавать) является символ новой строки ('\n').  В отличие от функции get функция getline  терминатор  в  массив  buf  считывает и из istream удаляет.

Можно прочитать "сырые"  двоичные  данные с помощью функции read:

         istream& istream::read( signed char* ptr, int n);

        istream& istream::read( unsigned char* ptr, int n);

    Пример:

       cin.read ( (char*)&x, sizeof(x) );

    Для типа  char*  (рассматриваемого как строка) действие операции >> состоит в пропуске пробельных символов  и  записи следующих  (не пробельных)  символов  до  тех  пор,  пока не встретится следующий пробельный  символ.  Затем  добавляется завершающий  нулевой  (0) символ. Следует предъявлять осторожность и избегать "переполнения" строки. Ширина по умолчанию, равная  нулю (означает,  что предельное значение не задано), может быть изменена при помощи width (или setw) следующим образом:

   char array[SIZE];

   ...

   // инициализация массива

   ...

   cin.width(sizeof(array));

   cin >> array      // позволяет избежать переполнения

    В случае любого ввода встроенных типов, если конец ввода встретится ранее первого не пробельного  символа, в мишень buf ничего записано не будет, а состояние istream будет установлено равным "отказу".  Таким образом,  если мишень  была  не инициализирована,  то она и останется не инициализированной.

Функция возвращения

     Функция-компонент

   istream istream::putback(char c);

возвратит обратно в istream один символ  c;  если  этот символ  не  может  быть помещен обратно,  то устанавливается состояние потока "отказ".

Позиционирование потока

Функция seekg() может содержать один или два аргумента: в качестве первого – требуемая позиция курсора или величина смещения, если присутствует второй  аргумент; второй -  смещение на величину первого аргумента. Второй аргумент может быть один из флагов:

ФлагНазначениеios::begios::curios::endСмещение от начала файлаСмещение от текущего положения курсораСмещение от конца файла

 Пример:

io.seekg(5,ios::end);

io.seekg(5,ios::beg);

 Пример: Выполнить чтение из файла построчно по 80 символов в каждой строке с выводом считанных данных на экран.

#include <fstream.h>

#define col 80

void main()

{

char str[col];

ifstream fstr(“a.cpp”);

while(fstr){

      fstr.getline(str,col);

      cout<<’\n’<<str;

      }

fstr.close();

}

Класс ostream

Функции управления потоковым выводом сосредоточены в классе оstream. С каждым из объектов этого класса и его производных связан объект класса streambuf. Функции класса оstream, доступные его потомкам, перечислены в таблице.

ФункцияНазначениеopfxВызывается перед операцией записи для проверки наличия ошибок в потокеosfxВызывается после каждой операции записи для очистки буфераputЗаписывает в поток одиночный байтwriteЗаписывает в поток требуемое число байтовflushОчищает буфер потока; аналогичное действие выполняет манипулятор flushseekpПеремещает маркер, обозначающий текущую позицию записи, на требуемую позицию в потокеtellpВозвращает позицию маркера записи  

Функции вывода put и write

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

        ostream ostream::put (char ch);

    При объявлении int ch='x'; следующие две строки эквивалентны:

         cout.put(ch);

         cout << (char)ch;

    Функция-компонент write позволяет  вывод больших по размеру объектов:

        ostream& ostream::write( signed char* ptr, int n);

        ostream& ostream::write( unsigned char* ptr, int n);

    Функции write выводят n символов (включая любые входящие пустые символы) в двоичном формате.  В отличие  от  строковой вставки, write не прекращает работу, встретив пустой символ.

Например,

        int x; char s[12];

        cout.write((char *)&x, sizeof(x));

        cout.write(s,sizeof(s));

пошлет не преобразованное представление  х и s на стандартное устройство вывода.

    Существует тонкое различие между форматированной операцией << и неформатированными функциями put и write. Форматированная  операция  может  вызвать очистку связанных потоков и иметь атрибут ширины поля. Неформатированные операции не  обладают  этими  свойствами.  Поэтому  cout  << 'a' и cout put('a') могут давать разные результаты. Все флаги форматирования применимы к <<,  но ни один из них не применим к put или write.

Пример: В файл, открытый в текстовом режиме, дважды записывается одна и та же строка: первый раз – посимвольно; второй – вся строка целиком.

#include <fstream.h>

#include <string.h>

#define n 40

main()

{ int i=0;

 char str[n]="Записываемая строка\n";

 ofstream fstr("ofstream.out");

 while(str[i] !='\0')

 {fstr.put(str[i]);

  cout<<"\nПозиция маркера записи: "<<fstr.tellp();

  i++;}

  fstr.write(str,strlen(str));

  cout<<"\nНовая позиция маркера записи: "<<fstr.tellp();

 fstr.close();

}

Результат:

Позиция маркера записи: 1

Позиция маркера записи: 2

…   …  …

Позиция маркера записи: 19

Позиция маркера записи: 21

Новая позиция маркера записи: 42

При выводе данных в файл, открытый в текстовом режиме, автоматически выполняется преобразование \n = CR/LF, т.е. символ новой строки преобразуется в пару символов возврата каретки и перевода строки. При чтении происходит обратное преобразование. Именно поэтому наблюдается  “скачок” счетчика: после 19 идет 21. Функция put(), записывающая в файл \n, на самом деле помещает в файл два других символа. Функция write() выполняет такое же преобразование, поэтому конечное число счетчика равно 42, а не 41.

Если в данной программе указать не текстовый, а двоичный файл

   ofstream fstr("ofstream.out", ios::binary);   

то такого “скачка” счетчика наблюдаться не будет, т.к. не происходит замены символа новой строки в пару символов возврата каретки и перевода строки.

Функции класса filebuf

Таблица                                             Функции класса filebuf

ФункцияНазначениеopenОткрывает файл для чтения/записи, связывая с ним объект класса filebufcloseЗакрывает файлsetmodeЗадает режим доступа к файлу: двоичный (константа filebuf::binary) или текстовый (константа filebuf::text)attachСвязывает указанный открытый файл с объектом класса filebuffdВозвращает дескриптор классаis_openПроверяет, открыт ли файл, связанный с потоком

Функции класса streambuf

  Семейство функций-элементов streambuf используется классами, основанными на ios. Любой класс, порожденный от ios, наследует указатель на объект класса streambuf.  Объекты класса streambuf управляют фиксированной областью памяти, называемой также областью резервирования, которая в свою очередь может быть разделена на область ввода и вывода ( они могут перекрывать друг друга).

  Класс streambuf является абстрактным, т.е. создать его объект напрямую нельзя (его конструктор является защищенным и не может быть вызван из программы). Можно создавать собственные классы, порожденные от streambuf, переопределяя его виртуальные функции и настраивая его работу в соответствии с потребностями конкретного приложения. Только из производных классов можно вызвать многочисленные защищенные функции этого класса, управляющие областью резервирования.

  Таблица                            Открытые функции класса streambuf

ФункцияНазначениеin_availВозвращает число символов в области вводаsgetcВозвращает символ, на который ссылается указатель области ввода; при этом указатель не перемещаетсяsnextcПеремещает указатель области ввода на одну позицию вперед, после чего возвращает текущий символsbumpcВозвращает текущий символ и затем перемещает указатель области ввода на одну позицию впередstosscПеремещает указатель области ввода на одну позицию вперед, но не возвращает символsputbackcПеремещает указатель области ввода на одну позицию назад,  возвращая символ в буферsgetnЧитает требуемое количество символов из буфераout_waitingВозвращает число символов в области выводаsputcЗаписывает символ в буфер и перемещает указатель области вывода на одну позицию впередsputnЗаписывает требуемое количество символов в буфер и перемещает указатель области вывода на соответствующее число позиций впередdbpВ текстовом виде записывает в стандартный выходной поток различного рода информацию о состоянии буфера

 Таблица                                   Виртуальные функции класса streambuf

ФункцияНазначениеbaseВозвращает указатель на начало области резервированияebufВозвращает указатель на конец области резервированияblenВозвращает размер области резервированияpbaseВозвращает указатель на начало области выводаpptrВозвращает значение указателя области выводаepptrВозвращает указатель на конец области вводаebackВозвращает указатель на начало области вводаgptrВозвращает значение указателя области вводаegptrВозвращает указатель на конец области выводаsetpЗадает значения указателей, связанных с областью выводаsetgЗадает значения указателей, связанных с областью вводаpbumpПеремещает указатель области вывода на указанное число байтов относительно текущей позицииgbumpПеремещает указатель области ввода на указанное число байтов относительно текущей позицииsetbЗадает значения указателей, связанных с областью резервированияunbufferedЗадает или возвращает значение переменной, определяющей состояние буфера allocateВызывает виртуальную функцию doallocate для создания области резервированияdoallocateВыделяет память для области резервирования ( виртуальная функция)

 Таблица                                   Виртуальные функции класса streambuf

ФункцияНазначениеsyncОчищает области ввода и выводаsetbufДобавляет к буферу указанную зарезервированную область памятиseekoffПеремещает указатель области ввода или вывода на указанное количество байтов seekposПеремещает указатель области ввода или вывода на указанную позицию относительно начала потокаoverflowОчищает область выводаunderflowЕсли область ввода пуста, заполняет ее данными из источникаpbackfailВызывается функцией sputbackc() в случае неудачной попытки вернуться назад на один символ

Функции класса strstreambuf

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

  •  без параметров – в этом случае в памяти создается буфер неопределенного размера, увеличивающегося или уменьшающегося при необходимости, а выделение и освобождение памяти осуществляется внутри класса strstreambuf;
  •  с одним целочисленным параметром - в этом случае в памяти создается буфер указанного начального размера, увеличивающегося или уменьшающегося при необходимости, а выделение и освобождение памяти осуществляется внутри класса strstreambuf;
  •  с двумя параметрами типа char* и int – в этом случае в качестве буфера используется уже выделенная область памяти указанного размера;
  •  с двумя указателями на функции, выполняющими динамическое выделение и удаление памяти для буфера, когда в этом возникает необходимость.

 В классе strstreambuf содержится всего две функции:

  •  freeze() – запрещает или разрешает автоматическое удаление и корректировку размера буфера, если тот создается внутри класса strstreambuf;
  •  str() – возвращает указатель на строку, хранящуюся в буфере.

Пример:

#include <strstrea.h>

#define n 1024

main()

{ char c;

  strstreambuf strbu(n);

  strbu.sputc(‘A’);

  c=strbu.sgetc();   cout<<c;

}

Результат:

А

Как уже было сказано, с указателями областей ввода и вывода в классе strstreambuf можно работать независимо друг от друга. Поэтому когда функция sputc() записывает в буфер символ ‘A’ и переводит указатель позиции записи на следующую позицию, указатель позиции чтения остается в исходной позиции, в результате чего функция  sgetc() возвращает только что записанный символ.

Определение состояния потока

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

ФункцияНазначениеeof()fail()bad()good()rdstate()clear()Возвращает ненулевое значение при обнаружении конца файлаВозвращает ненулевое значение при обнаружении какой-либо ошибки в потоке, возможно не фатальной: если функция bad() при этом возвращает 0, то, скорее всего, можно продолжать работу с потоком, предварительно сбросив флаг  ios::failbitВозвращает ненулевое значение при обнаружении серьезной ошибки ввода-вывода; в этом случае продолжать работу с потоком не рекомендуетсяВозвращает ненулевое значение, если биты состояния не установленыВозвращает текущее состояние потока в виде одной из констант: ios::goodbit(нет ошибки), ios::eofbit(достигнут конец файла), ios::failbit(возможно, не критическая ошибка форматирования или преобразования), ios::badbit(критическая ошибка)Задает состояние потока; принимает аргумент типа int, который по умолчанию равен 0, что соответствует сбросу всех битов состояния, в противном случае содержит одну или несколько перечисленных в предыдущем пункте констант, объединенных с помощью операции побитового ИЛИ (|)

Пример:

#include<fstream.h>

void main()

{  int fp;

ifstream fl("file1.doc",ios::in);

if(fl.eof()) fl.clear(); // состояние потока сбрасывается

if(fl.fail())

cerr<<"ошибка при создании файла\n";

if(fl.good()) cin>>fp;

if(!fl)    //другой способ обнаружения ошибки

cerr<<"ошибка при создании файла\n";

}

← Предыдущая
Страница 1
Следующая →

Скачать

Л8.doc

Л8.doc
Размер: 323 Кб

Бесплатно Скачать

Пожаловаться на материал

Описание к данному материалу отсутствует

У нас самая большая информационная база в рунете, поэтому Вы всегда можете найти походите запросы

Искать ещё по теме...

Похожие материалы:

Критерии оценки рекламных текстов

Критерии оценки рекламной литературы можно разделить на три группы или, по значимости (с некоторой долей условности), на критерии трех рангов. Затяжное печенье.

Имитатор сигнала стандарта GSM

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

Муниципальное право

Муниципальное право - как комплексная отрасль права. Муниципально-правовые нормы и отношения. Местное самоуправление в системе народовластия. Предметы ведения и полномочия местного самоуправления. Территориальная основа местного самоуправления. Правовые акты органов местного самоуправления и должностных лиц местного самоуправления. Финансово-экономические основы местного самоуправления. Институты непосредственной демократии в системе местного самоуправления. Органы местного самоуправления в системе народовластия. Муниципальная служба.

Примерный список вопросов к зачету  по дисциплине «Базы данных»

Научное познание

Стремление человека к познанию привело к возникновению различных видов знания. Определенные знания о мире и человеке дают и миф, и искусство, и религия.

Сохранить?

Пропустить...

Введите код

Ok