Источник: Nuances of Programming
Какой язык программирования вам подойдет? Пройдите тест SkillFactory из 7 вопросов и узнайте, какой язык программирования подходит лично вам.
Файлы делятся на две категории:
- текстовые;
- двоичные.
В текстовом файле содержатся символы ASCII, а каждая строка заканчивается специальным символом, которым в каждой операционной системе определяется конец строки. Например, в Unix это символ \n.
Двоичные файлы состоят из нечитаемого содержимого и не разбиваются на строки, поэтому необходимости в специальных символах нет.
Двоичные файлы обычно меньше текстовых по размеру: в последних для представления содержимого всегда используются символы ASCII, а в двоичных файлах — количество байтов, необходимое для каждого элемента содержимого.
Наконец, в двоичном файле чтение и запись быстрее.
Открытие файла
Файл открывается функцией fopen():
FILE *fopen(const char *filename, const char *mode)
// с помощью filename объявляется имя файла
// с помощью mode объявляется выполняемое действие (см. таблицу ниже)
Когда файл для редактирования находится в одной папке с исполняемым файлом, просто включаем filename, когда они в разных папках — задаем в качестве filename путь к файлу:
// файл в одной папке с исполняемым
fopen("test_file.txt", r);
// файл находится в другом каталоге
fopen("C:/boot/grub/gfxblacklist.txt", a+);
Рекомендуется всегда проверять возвращаемое в fopen() значение. Файл редактируется, только когда значение не NULL:
if ((check = fopen(filename, 'r')) == NULL)
Редактирование файла
- fseek();
- ftell();
- fputs();
- fprintf();
- putc();
- fscanf();
- fgets();
- getc();
- fread();
- fwrite().
fseek()
В каждом открытом файле имеется индекс для указания позиции следующего редактирования. Например, когда файл открывается в режиме чтения, индекс помещается в начало файла, а в режиме добавления — в конец.
После каждого редактирования позиция индекса обновляется автоматически. Индекс перемещается функцией fseek():
int fseek(FILE *indx, long int offset, int origin);
/*в fseek индекс перемещается от параметра исходного положения origin на число байтов, указанное в indx параметром смещения offset*/
// смещение бывает и отрицательным, тогда индекс перемещается «назад»
Параметром offset определяется исходное положение перемещаемого индекса:
Если индекс перемещен, в fseek() возвращается 0, если нет — целое число, отличное от нуля:
fseek(indx, 0, SEEK_END);
// Перемещение в конец файла
fseek(indx, 0, SEEK_SET);
// Перемещение в начало файла
fseek(indx, 44, SEEK_CUR);
// Перемещение на 44 байта вперед от текущей позиции
fseek(indx, -7, SEEK_CUR);
// Перемещение на 7 байт назад от текущей позиции
В двоичных файлах fseek() применяется без проблем, но при работе с текстовыми необходимо учитывать специальный символ строк.
ftell()
Функцией ftell() определяется текущее положение индекса. Ею возвращается число байтов от начала файла до индекса:
long int ftell(FILE *indx);
fputs()
Функцией fputs() в текстовый файл добавляется строка:
int fputs(const char *str, FILE *fptr);
/*параметр str — это указатель на
добавляемую в файл строку*/
Например:
fptr = fopen("test_file.txt", 'w');
fputs ("Hello World!\n" , fptr);
fprintf()
Функцией fprintf() содержимое выводится в файле, в отличие от printf() и ее стандартного вывода на экран stdout.
Если редактирование успешно, возвращается число добавленных в файл символов, если нет — отрицательное значение:
int fprintf(FILE *fptr, const char *format, ...);
Например:
FILE* fptr;
int i;
fptr = fopen("test_file.txt", 'w');
for (i = 0; i < 5; i++)
fprintf(fptr, "%d %s\n", i , "Hello World!");
putc()
Функцией putc() в файл добавляется символ. Если редактирование успешно, в функции возвращается записанный в файле символ, если нет — конец файла EOF:
int putc(int ch, FILE *fptr);
// ch — это символ, записываемый в файле, указанном в fp
В примерах выше, если вместо параметра fp задать stdout, результаты выведутся на экран.
fscanf()
Функцией fscanf() в текстовом файле сканируются различные данные. В двоичных файлах это тоже возможно, но не рекомендуется. В fscanf() данные считываются из файла, в отличие от scanf() с ее приемом ввода из stdin.
Возвращается число считанных элементов, присвоенных переменным. Если fscanf() задействуется в конце файла или случаются любые другие проблемы, в функции возвращается EOF:
int fscanf(FILE *fp, const char *format, ...);
fgets()
Функцией fgets() символы в файле считываются до специального символа новой строки или последнего символа файла.
Если fgets() выполняется успешно, символы сохраняются в переменной с указателем и возвращается этот указатель, если нет — возвращается NULL:
char *fgets(char *str, int size, FILE *fptr);
// str — это указатель на то, где сохранятся символы
// Параметром size определяется количество считываемых символов
getc()
Функцией getc() в файле считывается один символ. Если getc() выполняется успешно, возвращается считанный символ, если нет — EOF:
int getc(FILE *fptr);
Возвращаемое значение должно сохраняться в переменной int, а не char.
fwrite()
Функцией fwrite() в файле записываются большие объемы данных:
int fwrite(const void *data, size_t size, size_t count, FILE *fptr);
/*data — это указатель на адрес памяти
добавляемых в файл данных;
чтобы сохранять данные любого типа, он объявлен как void*/
// данные сохраняются в файле, обозначаемом указателем fptr
// параметром count указывается число сохраняемых элементов
// параметром size указывается размер каждого элемента в байтах
Например:
// сохранение в файле массива 44 элементов
int array[44];
fwrite(array, sizeof(int), 44, fptr);
fread()
Функцией fread() считываются большие объемы данных. Возвращается число считанных из загруженного файла элементов.
Если это значение не равно параметру count в примере ниже, значит, при загрузке файла произошла ошибка или мы добрались до конца файла:
int fread(void *data, size_t size, size_t, count FILE *fptr);
/*data — это указатель на адрес памяти переменной, в которой сохранятся считываемые из файла данные;
чтобы сохранять данные любого типа, он объявлен как void*/
// параметром count указывается число считываемых элементов
// параметром size указывается размер каждого элемента в байтах
Например:
// считывание в файле массива 700 элементов
int array[700];
fread(array, sizeof(int), 700, fptr);
feof()
Этой функцией определяется, добрались ли мы до конца файла. Если в функции считывания данные считываются после окончания файла, в feof() возвращается ненулевое значение, если до — 0:
int feof(FILE *fptr);
Например:
FILE *fptr;
char array[40];
fptr = fopen("test_file.txt", 'r');
// предполагается, что файл успешно загружен
// так мы не проверяем, не NULL ли значение fptr
if (fgets(array, sizeof(str), fptr) != NULL)
print("%s", array);
else
{
if(feof(fptr))
printf("End of file\n");
else
printf("Failed for another reason\n");
}
Закрытие файла
Файл закрывается функцией fclose():
int flcose(FILE *fptr);
// fptr нужен для указания файла
/*функция объявлена как int: если файл закрывается, в ней возвращается 0, если нет — EOF*/
Хотя при завершении программы файл закрывается автоматически, все равно рекомендуется использовать функцию fclose(): в случае нежелательного или аварийного завершения данные останутся невредимыми.
Вот и все. Это была обработка файлов на C. Рекомендую ознакомиться с каждой функцией чуть подробнее: в одной статье всего не разберешь.
Файлы предполагают разнообразные практические упражнения и идеи для начинающих, с ними возможно сохранение выходных данных программ и при необходимости выполнение нескольких операций.
Читайте также:
Перевод статьи Alopix | Αλώπηξ: C:File Handling