Работа с файлами
Операции с файлами Для того чтобы можно было читать из файла или писать в файл, он должен быть предварительно открыт с помощью библиотечной функции fopen. Функция fopen получает внешнее имя файла, после чего осуществляет некоторые организационные действия и "переговоры" с операционной системой и возвращает указатель, используемый в дальнейшем для доступа к файлу. Этот указатель, называемый указателем файла, ссылается на структуру, содержащую информацию о файле (адрес буфера, положение текущего символа в буфере, открыт файл на чтение или на запись, были ли ошибки при работе с файлом и не встретился ли конец файла).
Тип FILE FILE *fp; FILE *fopen(char *name, char *mode); Это говорит, что fp есть указатель на FILE, a fopen возвращает указатель на FILE. FILE это имя типа, наподобие int, а не имя структуры.
fopen() Обращение к fopen в программе может выглядеть следующим образом: fp = fopen(name, mode); Первый аргумент строка, содержащая имя файла. Второй аргумент несет информацию о режиме. Это тоже строка: в ней указывается, каким образом пользователь намерен применять файл. Возможны следующие режимы: чтение (read "r"), запись (write "w") и добавление (append "а"), т. е. запись информации в конец уже существующего файла. В некоторых системах различаются текстовые и бинарные файлы; в случае последних в строку режима необходимо добавить букву "b" (binary бинарный).
fopen() Тот факт, что некий файл, которого раньше не было, открывается на запись или добавление, означает, что он создается (если такая процедура физически возможна). Открытие уже существующего файла на запись приводит к выбрасыванию его старого содержимого, в то время как при открытии файла на добавление его старое содержимое сохраняется. Попытка читать несуществующий файл является ошибкой. Могут иметь место и другие ошибки; например, ошибкой считается попытка чтения файла, который по статусу запрещено читать. При наличии любой ошибки fopen возвращает NULL.
fclose() int fclose(FILE *fp) Функция, обратная по отношению к fopen; она разрывает связь между файловым указателем и внешним именем (которая раньше была установлена с помощью fopen), освобождая тем самым этот указатель для других файлов. Так как в большинстве операционных систем количество одновременно открытых одной программой файлов ограничено, то файловые указатели, если они больше не нужны, лучше освобождать.
getc() int getc(FILE *fp) Функция getc возвращает следующий символ из потока, на который указывает *fp; в случае исчерпания файла или ошибки она возвращает EOF.
putc() Функция putc пишет символ c в файл fp int putc(int с, FILE *fp) и возвращает записанный символ или EOF в случае ошибки.
Стандартные потоки При запуске Си-программы операционная система всегда открывает три файла и обеспечивает три файловые ссылки на них. Этими файлами являются: стандартный ввод, стандартный вывод и стандартный файл ошибок; соответствующие им указатели называются stdin, stdout и stderr; они описаны в.
Ввод и вывод файлов Форматный ввод-вывод файлов можно построить на функциях fscanf и fprintf. Они идентичны scanf и printf с той лишь разницей, что первым их аргументом является указатель на файл, для которого осуществляется ввод-вывод, формат же указывается вторым аргументом. int fscanf(FILE *fp, char *format,...) int fprintf(FILE *fp, char *format,...)
Аргументы командной строки #include int main(int argc, char *argv[]) { int i = 0; while(i<argc) { printf("Argument %d: %s\n", argc, argv[i]); i++; } return 0; }
#include /* cat: конкатенация файлов, версия 1 */ int main(int argc, char *argv[]) { FILE *fp; void filecopy(FILE *, FILE *); if (argc == 1) /* нет аргументов; копируется стандартный ввод */ filecopy(stdin, stdout); else while (--argc > 0) if ((fp = fopen(*++argv, "r")) == NULL) { printf("cat: не могу открыть файл %s\n", *argv); return 1; } else { filecopy(fp, stdout); fclose(fp); } return 0; }
/* filecopy: копирует файл ifp в файл ofp */ void filecopy(FILE *ifp, FILE *ofp) { int c; while ((c = getc(ifp)) != EOF) putc(c, ofp); }
#include /* cat: конкатенация файлов, версия 2 */ int main(int argc, char *argv[]) { FILE *fp; void filecopy(FILE *, FILE *); char *prog = argv[0]; /* имя программы */ if (argc ==1) /* нет аргументов; копируется станд. ввод */ filecopy(stdin, stdout); else while (--argc > 0) if ((fp = fopen(*++argv, "r")) == NULL) { fprintf (stderr, "%s: не могу открыть файл %s\n", prog, *argv); exit(1); } else { filecopy(fp, stdout); fclose(fp); } if (ferror(stdout)) { fprintf (stderr, "%s: ошибка записи в stdout\n", prog); exit(2); } exit(0); }
ferror() Функция ferror выдает ненулевое значение, если при работе с файлом fp была обнаружена ошибка. int ferror(FILE *fp)
feof() Функция feof(FILE *) возвращает ненулевое значение, если встретился конец указанного в аргументе файла. int feof(FILE *fp)
fgets() char *fgets(char *line, int maxline, FILE *fp) Функция fgets читает следующую строку ввода (включая и символ новой строки) из файла fp в массив символов line, причем она может прочитать не более MAXLINE-1 символов. Переписанная строка дополняется символом '\0'. Обычно fgets возвращает line, а по исчерпании файла или в случае ошибки NULL.
fputs() int fputs(char *line, FILE *fp) Эта функция возвращает EOF, если возникла ошибка, и неотрицательное значение в противном случае. Библиотечные функции gets и puts подобны функциям fgets и fputs. Отличаются они тем, что оперируют только стандартными файлами stdin и stdout, и кроме того, gets выбрасывает последний символ '\n', a puts его добавляет.
fread() size_t fread(void *ptr, size_t size, size_t nobj, FILE *stream) fread читает из потока stream в массив ptr не более nobj объектов размера size. Она возвращает количество прочитанных объектов, которое может быть меньше заявленного. Для индикации состояния после чтения следует использовать feof и ferror.
fwrite() size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *stream) fwrite пишет из массива ptr в stream nobj объектов размера size ; возвращает число записанных объектов, которое в случае ошибки меньше nobj.
fseek() int fseek(FILE *stream, long offset, int origin) fseek устанавливает позицию для stream ; последующее чтение или запись будет производиться с этой позиции. В случае бинарного файла позиция устанавливается со смещением offset относительно начала, если origin равен SEEK_SET. Относительно текущей позиции, если origin равен SEEK_CUR. И относительно конца файла, если origin равен SEEK_END. Для текстового файла offset должен быть нулем или значением, полученным с помощью вызова функции ftell. При работе с текстовым файлом origin всегда должен быть равен SEEK_SET.
ftell() long ftell(FILE *stream) ftell возвращает текущую позицию потока stream или -1L, в случае ошибки.
rewind() void rewind(FILE *stream) rewind (fp) делает то же, что и fseek(fp, 0L, SEEK_SET);
/* fgets: получает не более n символов из iop */ char *fgets(char *s, int n, FILE *iop) { register int c; register char *cs; cs = s; while (--n > 0 && (c = getc(iop)) != EOF) if ((*cs++ = c) == '\n' ) break; *cs = '\0' ; return (c == EOF && cs == s) ? NULL : s; } /* fputs: посылает строку s в файл iop */ int fputs(char *s, FILE *iop) { int c; while (c = *s++) putc(c, iop); return ferror(iop) ? EOF : 0; }