Работа с файлами в си ввод и вывод в файл в си
В этой статье мы узнаем, как считывать данные из файлов и записывать информацию в файлы в программах си. Файлы в си используются для того, чтобы сохранять результат работы программы си и использовать его при новом запуске программы . Например можно сохранять результаты вычислений , статистику игр.
Чтобы работать с файлами в си необходимо подключить библиотеку stdio.h
#include <stdio.h>
Чтобы работать с файлом в си необходимо задать указатель на файл по образцу
FILE *имя указателя на файл;
Например
FILE *fin;
Задает указатель fin на файл
Дальше необходимо открыть файл и привязать его к файловому указателю. Для открытия файла в си на чтение используется команда
Имя указателя на файл= fopen("путь к файлу", "r");
Например следующая команда
fin = fopen("C:\\Users\\user\\Desktop\\data.txt", "r");
откроет файл data.txt, находящийся на рабочем столе по пути C:UsersuserDesktop Чтобы узнать путь к файлу можно выбрать файл мышью нажать на правую кнопку мыши и выбрать свойства файла. В разделе Расположение будет указан путь к файлу. Обратите внимание , что в си путь указывается с помощью двух слешей.
После работы с файлом в си , необходимо его закрыть с помощью команды
fclose(имя указателя на файл)
Считывание информации из текстового файла в Си
Чтобы можно было считывать русские символы из файла, необходимо настроить работу с Кириллицей с помощью команды
setlocale(LC_ALL, "Russian");
При этом необходимо в начале программы подключить #include <iostream>
Оператор fscanf()
Для считывания слова из файла в си используется команда fscanf(). Эта команда аналогична команде ввода информации с клавиватуры в си scanf() только первый параметр это указатель на файл
fscanf(указатель на файл,"%формат ввода данных1% форматввода данных2…",&перменная1,&переменная2…);
Например команда
fscanf(fin,"%d%d%d",&a,&b,&c);
считает из файла, который привязан к указателю на файл fin строку из трех целочисленных переменных
Разберем пример программы, которая считывает из текстового файла data.txt в которые записаны три столбца цифр информацию и записывает ее в массивы. Для каждого столбца информации свой массив. Подробно о работе с массивами в Си.
#include <stdio.h>
#include <conio.h>
main()
< int a[10];
int b[10];
int c[10];
int i;
// определяем указатель на файл
FILE *fin;
// открываем файл на чтение
fin = fopen("C:\\Users\\user\\Desktop\\data.txt", "r");
// построчное считывание из файла
for (i=0;i<3;i++)
<
// считывание строки из трех значений файла и запись в массивы
fscanf(fin,"%d%d%d",&a[i],&b[i],&c[i]);
>
// вывод массивов на экран
for (i=0;i<3;i++)
<
printf("%d %d %d\n",a[i],b[i],c[i]);
>
getch();
// закрытие файла
fclose(fin);
>
Построковое считывание информации из файла в СИ.Функция fgets ( )
Оператор fscanf() считывает из файла слово , т.е. до первого встречного пробела.
Чтобы считать из файла всю строку из файла в Си используется конструкция
if ( NULL != fgets (строковая переменная, длина строки, указатель на файл ) )
<
действия при считывании строки
>
Например программа на Си которая считывает две строки из файла и выводит их на экран
#include <stdio.h>
#include <conio.h>
#include <iostream>
main()
<
// задаем строковые перменные
char st1[100];
char st2[100];
//определяем указатель на файл
FILE *fin;
// настриваем работу с Кириллицей
setlocale(LC_ALL, "Russian");
// открываем файл на чтение
fin = fopen("C:\\data.txt", "r");
// считываем первую строку из файла
if ( NULL != fgets ( st1, 100, fin ) )
<
// выводим строку на экран
printf("%s ",st1);>
// считываем вторую строку из файла
if ( NULL != fgets ( st2, 100, fin ) )
<
// выводим строку на экран
printf("%s\n",st2);>
// закрываем файл на чтение
fclose(fin);
>
Запись информации в текстовый файл в Си
Для записи данных в файл в Си, необходимо открыть файл в режиме записи
Имя указателя на файл= fopen("путь к файлу", "w");
Для записи в строку текстового файла используется команда fprnitf(), которая аналогична команде printf() вывод на экран в си только первый параметр это указатель на файл
fprintf (имя указателя на файл,”%формат ввода”, переменные);
Например запись в файл out.txt значение переменной а
a=10;
fout = fopen("C:\\Users\\user\\Desktop\\out.txt", "w");
fprintf (fout,”%d”, a);
Пример программы на си которая запрашивает два числа и записывает в файл out.txt оба эти числа и их сумму
#include <stdio.h>
#include <conio.h>
Вернуться к содержанию Перейти к уроку Ошибки в программах на си
Как считать вторую строку из файла c
При работе с текстовыми файлами граздо проще работать с данными не как с отдельными символами, а как со строками с помощью функций fgets() и fputs() .
Запись текстового файла
Функция fputs() записывает в файл строку, то есть набор символов, который завершается символом ‘\0’. Она имеет следующий прототип:
Первый параметр функции — записываемая строка, а второй — указатель на файловый поток. В качестве результата функция возвращает неотрицательное целое число. При ошибках в процессе записи возвращается значение EOF .
При записи строки нулевой символ ‘\0’ в файл не записывается.
Например, запишем строку в файл:
Запись довольно проста: открываем файл на запись и с помощью вызова fputs(message, fp) записываем в файл искомую строку.
Чтение текстового файла
Функция fgets() считывает из файла одну строку и имеет следующий прототип:
Первый параметр char *s представляет строку, в которую производится считывание. Второй параметр — число n указывает, сколько символов необходимо считывать. И третий параметр представляет файловый поток, из которого производится считывание.
При вызове функция считывает из файла не более n-1 символов. Функция прекращает чтение, когда прочтет n-1 символов или встретит символ переноса строки \n. Все считанные символы записываются в строку s, в том числе символ \n. И также конец каждой строки дописывается нулевой символ ‘\0’.
При успешном завершении функция возвращает указатель s , а при ошибке или достижении конца файла возвращается значение NULL .
Считаем данные из выше записанного файла «data.txt»:
Здеcь открываем файл на чтение и в цикле считываем из файла по 256 символов и выводим их на консоль с помощью вызова fgets(cc, 256, fp) . Когда данные в файле закончатся, функция возвратит NULL, и произойдет выход из цикла.
Копирование файлов
Другой пример работы с текстовыми файлами — копирование содержимого из одного файла в другой:
Прочитать конкретную строчку файла C#
Мне нужно записать в переменную не весь файл, а только вторую строку. Как это сделать?
PS: сори за потенциально тупой вопрос, но это важно.
![]()
![]()
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.3.11.43304
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Работа с текстовыми файлами
Р абота с текстовым файлом похожа работу с консолью: с помощью функций форматированного ввода мы сохраняем данные в файл, с помощью функций форматированного вывода считываем данные из файла. Есть множество нюансов, которые мы позже рассмотрим. Основные операции, которые необходимо проделать, это
- 1. Открыть файл, для того, чтобы к нему можно было обращаться. Соответственно, открывать можно для чтения, записи, чтения и записи, переписывания или записи в конец файла и т.п. Когда вы открываете файл, может также произойти куча ошибок – файла может не существовать, это может быть файл не того типа, у вас может не быть прав на работу с файлом и т.д. Всё это необходимо учитывать.
- 2. Непосредственно работа с файлом — запись и чтение. Здесь также нужно помнить, что мы работаем не с памятью с произвольным доступом, а с буферизированным потоком, что добавляет свою специфику.
- 3. Закрыть файл. Так как файл является внешним по отношению к программе ресурсом, то если его не закрыть, то он продолжит висеть в памяти, возможно, даже после закрытия программы (например, нельзя будет удалить открытый файл или внести изменения и т.п.). Кроме того, иногда необходимо не закрывать, а «переоткрывать» файл для того, чтобы, например, изменить режим доступа.
Кроме того, существует ряд задач, когда нам не нужно обращаться к содержимому файла: переименование, перемещение, копирование и т.д. К сожалению, в стандарте си нет описания функций для этих нужд. Они, безусловно, имеются для каждой из реализаций компилятора. Считывание содержимого каталога (папки, директории) – это тоже обращение к файлу, потому что папка сама по себе является файлом с метаинформацией.
Иногда необходимо выполнять некоторые вспомогательные операции: переместиться в нужное место файла, запомнить текущее положение, определить длину файла и т.д.
Для работы с файлом необходим объект FILE. Этот объект хранит идентификатор файлового потока и информацию, которая нужна, чтобы им управлять, включая указатель на его буфер, индикатор позиции в файле и индикаторы состояния.
Объект FILE сам по себе является структурой, но к его полям не должно быть доступа. Переносимая программа должна работать с файлом как с абстрактным объектом, позволяющим получить доступ до файлового потока.
Создание и выделение памяти под объект типа FILE осуществляется с помощью функции fopen или tmpfile (есть и другие, но мы остановимся только на этих).
Функция fopen открывает файл. Она получает два аргумента – строку с адресом файла и строку с режимом доступа к файлу. Имя файла может быть как абсолютным, так и относительным. fopen возвращает указатель на объект FILE, с помощью которого далее можно осуществлять доступ к файлу.
Например, откроем файл и запишем в него Hello World
Функция fopen сама выделяет память под объект, очистка проводится функцией fclose. Закрывать файл обязательно, самостоятельно он не закроется.
Функция fopen может открывать файл в текстовом или бинарном режиме. По умолчанию используется текстовый. Режим доступа может быть следующим
| Тип | Описание |
|---|---|
| r | Чтение. Файл должен существовать. |
| w | Запись нового файла. Если файл с таким именем уже существует, то его содержимое будет потеряно. |
| a | Запись в конец файла. Операции позиционирования (fseek, fsetpos, frewind) игнорируются. Файл создаётся, если не существовал. |
| r+ | Чтение и обновление. Можно как читать, так и писать. Файл должен существовать. |
| w+ | Запись и обновление. Создаётся новый файл. Если файл с таким именем уже существует, то его содержимое будет потеряно. Можно как писать, так и читать. |
| a+ | Запись в конец и обновление. Операции позиционирования работают только для чтения, для записи игнорируются. Если файл не существовал, то будет создан новый. |
Если необходимо открыть файл в бинарном режиме, то в конец строки добавляется буква b, например “rb”, “wb”, “ab”, или, для смешанного режима “ab+”, “wb+”, “ab+”. Вместо b можно добавлять букву t, тогда файл будет открываться в текстовом режиме. Это зависит от реализации. В новом стандарте си (2011) буква x означает, что функция fopen должна завершиться с ошибкой, если файл уже существует. Дополним нашу старую программу: заново откроем файл и считаем, что мы туда записали.
Вместо функции fgets можно было использовать fscanf, но нужно помнить, что она может считать строку только до первого пробела.
fscanf(file, «%127s», buffer);
Также, вместо того, чтобы открывать и закрывать файл можно воспользоваться функцией freopen, которая «переоткрывает» файл с новыми правами доступа.
Функции fprintf и fscanf отличаются от printf и scanf только тем, что принимают в качестве первого аргумента указатель на FILE, в который они будут выводить или из которого они будут читать данные. Здесь стоит сразу же добавить, что функции printf и scanf могут быть без проблем заменены функциями fprintf и fscanf. В ОС (мы рассматриваем самые распространённые и адекватные операционные системы) существует три стандартных потока: стандартный поток вывода stdout, стандартный поток ввода stdin и стандартный поток вывода ошибок stderr. Они автоматически открываются во время запуска приложения и связаны с консолью. Пример
Ошибка открытия файла
Если вызов функции fopen прошёл неудачно, то она возвратит NULL. Ошибки во время работы с файлами встречаются достаточно часто, поэтому каждый раз, когда мы окрываем файл, необходимо проверять результат работы
Проблему вызывает случай, когда открывается сразу несколько файлов: если один из них нельзя открыть, то остальные также должны быть закрыты
В простых случаях можно действовать влоб, как в предыдущем куске кода. В более сложных случаях используются методы, подменяющиее RAII из С++: обёртки, или особенности компилятора (cleanup в GCC) и т.п.
Буферизация данных
- 1) Если он заполнен
- 2) Если поток закрывается
- 3) Если мы явно указываем, что необходимо очистить буфер (здесь тоже есть исключения:)).
- 4) Также очищается, если программа завершилась удачно. Вместе с этим закрываются и все файлы. В случае ошибки выполнения этого может не произойти.
Форсировать выгрузку буфера можно с помощью вызова функции fflush(File *). Рассмотрим два примера – с очисткой и без.
Раскомментируйте вызов fflush. Во время выполнения откройте текстовый файл и посмотрите на поведение.
Буфер файла можно назначить самостоятельно, задав свой размер. Делается это при помощи функции
которая принимает уже открытый FILE и указатель на новый буфер. Размер нового буфера должен быть не меньше чем BUFSIZ (к примеру, на текущей рабочей станции BUFSIZ равен 512 байт). Если передать в качестве буфера NULL, то поток станет небуферизированным. Можно также воспользоваться функцией
- _IOFBF — полная буферизация. Данные записываются в файл, когда он заполняется. На считывание, буфер считается заполненным, когда запрашивается операция ввода и буфер пуст.
- _IOLBF — линейная буферизация. Данные записываются в файл когда он заполняется, либо когда встречается символ новой строки. На считывание, буфер заполняется до символа новой строки, когда запрашивается операция ввода и буфер пуст.
- _IONBF – без буферизации. В этом случае параметры size и buffer игнорируются.
Пример: зададим свой буфер и посмотрим, как осуществляется чтение из файла. Пусть файл короткий (что-нибудь, типа Hello, World!), и считываем мы его посимвольно
Видно, что данные уже находятся в буфере. Считывание посимвольно производится уже из буфера.
Функция int feof (FILE * stream); возвращает истину, если конец файла достигнут. Функцию удобно использовать, когда необходимо пройти весь файл от начала до конца. Пусть есть файл с текстовым содержимым text.txt. Считаем посимвольно файл и выведем на экран.
Всё бы ничего, только функция feof работает неправильно. Это связано с тем, что понятие «конец файла» не определено. При использовании feof часто возникает ошибка, когда последние считанные данные выводятся два раза. Это связано с тем, что данные записывается в буфер ввода, последнее считывание происходит с ошибкой и функция возвращает старое считанное значение.
Этот пример сработает с ошибкой (скорее всего) и выведет последний символ файла два раза.
Решение – не использовать feof. Например, хранить общее количество записей или использовать тот факт, что функции fscanf и пр. обычно возвращают число верно считанных и сопоставленных значений.
Примеры
1. В одном файле записаны два числа — размерности массива. Заполним второй файл массивом случайных чисел.
2. Пользователь копирует файл, при этом сначала выбирает режим работы: файл может выводиться как на консоль, так и копироваться в новый файл.
3. Пользователь вводит данные с консоли и они записываются в файл до тех пор, пока не будет нажата клавиша esc. Проверьте программу и посмотрите. как она себя ведёт в случае, если вы вводите backspace: что выводится в файл и что выводится на консоль.
4. В файле записаны целые числа. Найти максимальное из них. Воспользуемся тем, что функция fscanf возвращает число верно прочитанных и сопоставленных объектов. Каждый раз должно возвращаться число 1.
Другое решение считывать числа, пока не дойдём до конца файла.
5. В файле записаны слова: русское слово, табуляция, английское слово, в несколько рядов. Пользователь вводит английское слово, необходимо вывести русское.
Файл с переводом выглядит примерно так
солнце sun
карандаш pen
шариковая ручка pencil
дверь door
окно windows
стул chair
кресло armchair
и сохранён в кодировке cp866 (OEM 866). При этом важно: последняя пара cлов также заканчивается переводом строки.
Алгоритм следующий — считываем строку из файла, находим в строке знак табуляции, подменяем знак табуляции нулём, копируем русское слово из буфера, копируем английское слово из буфера, проверяем на равенство.
6. Подсчитать количество строк в файле. Будем считывать файл посимвольно, считая количество символов ‘\n’ до тех пор, пока не встретим символ EOF. EOF – это спецсимвол, который указывает на то, что ввод закончен и больше нет данных для чтения. Функция возвращает отрицательное значение в случае ошибки.
ЗАМЕЧАНИЕ: EOF имеет тип int, поэтому нужно использовать int для считывания символов. Кроме того, значение EOF не определено стандартом.

Всё ещё не понятно? – пиши вопросы на ящик