Операции ввода и вывода в файл Файлы Хранение данных в переменных и массивах является временным → все эти данные теряются при завершении работы программы Для постоянного хранения больших объемов данных используются файлы Файл Файл – группа связанных записей Бит 1 01001010 Байт (код символа J в ASCII) Judy Поле Sally Black Tom Brown Judy Green Iris Orange Randy Red Запись Judy Green Файлы Язык Си рассматривает любой файл как последовательный поток байтов 0 1 2 3 4 5 6 7 8 9 … n-1 Маркер конца файла EOF В начале исполнения программы открываются три файла и связанные с ними потоки: stdout (стандартный поток вывода), stdin (стандартный поток ввода) и stderr (стандартный поток ошибок) Каждому открытому файлу ставится в соответствие поток Открытый файл возвращает указатель на структуру FILE (определенную в stdio.h), которая содержит информацию, используемую при работе с файлом Эта структура включает дескриптор файла – индекс в массиве, называемом таблицей файлов Функции для работы с файлами Открытие файла (инициализация потока) FILE *fopen(char *path, char *mode); path – имя файла mode – режим открытия файла При успешном завершении fopen возвращают указатель на FILE, иначе возвращается NULL #include <stdio.h> FILE *fp; fp = fopen(“file.txt”, “r”); if(fp != NULL) { ... } Функции для работы с файлами Открытие файла (инициализация потока) Параметр mode может принимать следующие значения: Открыть текстовый файл для чтения. Чтение начинается с начала файла. Открыть для чтения и записи. Чтение или запись начинаются с начала файла. "Урезать" файл до нулевой длины или создать текстовый файл и открыть его для записи. Запись начинается с начала файла. w+ Открыть для чтения и записи. Файл создается, если до этого его не существовало, в противном случае он "урезается". Чтение или запись начинаются с начала файла. a Открыть для дописывания (записи в конец файла). Файл создается, если до этого его не существовало. Запись осуществляется в конец файла. a+ Открыть для чтения и дописывания (записи в конец файла). Файл создается, если до этого его не существовало. Чтение или запись производятся с конца файла. r r+ w Текстовые и двоичные файлы Поток можно открыть в текстовом или двоичном (бинарном) режиме В текстовом режиме прочитанная из потока комбинация символов CR (возврат каретки) и LF (перевод строки) преобразуются в один символ конца строки ‘\n’. При записи в поток в текстовом режиме осуществляется обратное преобразование, т.е. символ ‘\n’ преобразуется в комбинацию CR и LF. Если файл хранит не текстовую, а произвольную двоичную информацию, то такие преобразования не нужны. Обмен без такого преобразования выполняется при выборе бинарного режима, который обозначается буквой b. Например, “r+b” или “wb”. Функции для работы с файлами Закрытие файла (потока) Открытые файлы после окончания работы с ними рекомендуется закрывать int fclose (FILE *fp); #include <stdio.h> FILE *fp; fp = fopen(“file.txt”, “r”); if(fp != NULL) { ... } ... fclose(fp); Функции для работы с файлами Чтение из файла (потока) int getc(FILE *fp); int fgetc(FILE *fp); char* fgets(char *s, int n, FILE *fp); int fscanf(FILE *fp, char *format, ...); Функции для работы с файлами Запись в файл (поток) int int int int putc(int c, FILE *fp); fputc(int c, FILE *fp); fputs(char *s, FILE *fp); fprintf(FILE *fp, char *format, ...); Пример #include <stdio.h> int c; Enter, Ctrl + D while((c = getc(stdin)) != EOF) { putc(c, stdout); } Пример int c; FILE *fp; fp = fopen("file.dat", "w"); if(fp != NULL) { while((c = getc(stdin)) != 'a') { putc(c, fp); user@user-pc:~/Test$ ./a.out h } e fclose(fp); l } l o a Пример FILE *fp; char c; char fname[20]; printf(“Enter file name:\n”); scanf(“%s”, fname); if((fp = fopen(fname, “r“)) == NULL) { printf(“Cannot open file\n”); return 1; } while((c = getc(fp)) != EOF) user@user-pc:~/Test$ ./a.out Enter file name: { file.dat putc(c, stdout); h e } l fclose(fp); l return 0; o Пример Копирование содержимого одного файла в другой int main(int argc, char **argv) { char buf[256]; FILE *fr, *fw; if(argc != 3) { printf(“\nФормат вызова программы:”); printf(“\n%s”, argv[0]); printf(“\nфайл-источник файл-приемник”); return 1; } if((fr = fopen(argv[1], “r”)) == NULL) { printf(“Ошибка открытия файла %s”, argv[1]); return 1; } Пример if((fw = fopen(argv[2], “w”)) == NULL) { printf(“Ошибка открытия файла %s”, argv[2]); return 1; } while(fgets(buf, 256, fr) != NULL) { fputs(buf, fw); } fclose(fr); fclose(fw); return 0; } user@user-pc:~/Test$ ./a.out file.dat result.dat argv[0] argv[1] argv[2] Пример FILE *fp; int n; if((fp = fopen(“test”, “w”)) == NULL) { printf(“Cannot open \”test\””); return 1; } for(n = 1; n <= 10; n++) { fprintf(fp, “%d %d\n”, n, n * n); } fclose(fp); return 0; Пример FILE *fp; int n, i, nn; if((fp = fopen(“test”, “r”)) == NULL) { printf(“Cannot open \”test\””); return 1; } for(i = 1; i <= 10; i++) { fscanf(fp, “%d %d”, &n, &nn); printf(“%d %d\n”, n, nn); } fclose(fp); return 0; Ввод-вывод для бинарных файлов #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); Пример struct addr { char name[40]; char address[40]; char city[40]; char zip[40]; } info; FILE *fp; if((fp = fopen("bd.dat", "wb")) == NULL) { printf("He удается открыть файл.\n"); return 1; } strcpy(info.name, "SibSUTIS"); strcpy(info.address, "Kirov str. 86"); strcpy(info.city, "Novosibirsk"); strcpy(info.zip, "630102"); fwrite(&info, sizeof(struct addr), 1, fp); fclose(fp); return 0; Пример struct addr { user@user-pc:~/Test$ ./a.out char name[40]; Name: SibSUTIS char address[40]; Address: Kirov str. 86 char city[40]; City: Novosibirsk char zip[40]; Zipcode: 630102 } info; FILE *fp; if((fp = fopen("bd.dat", "rb")) == NULL){ printf("He удается открыть файл.\n"); return 1; } fread(&info, sizeof(struct addr), 1, fp); printf("\nName: %s", info.name); printf("\nAddress: %s", info.address); printf("\nCity: %s", info.city); printf("\nZipcode: %s", info.zip); fclose(fp); return 0;