No Image

Язык си работа с файлами

СОДЕРЖАНИЕ
0 просмотров
22 января 2020

Работа с файлами в си

В этой статье мы узнаем, как считывать данные из файлов и записывать информацию в файлы в программах си. Файлы в си используются для того, чтобы сохранять результат работы программы си и использовать его при новом запуске программы . Например можно сохранять результаты вычислений , статистику игр.
Чтобы работать с файлами в си необходимо подключить библиотеку stdio.h
#include
Чтобы работать с файлом в си необходимо задать указатель на файл по образцу
FILE *имя указателя на файл;
Например
FILE *fin;
Задает указатель fin на файл
Дальше необходимо открыть файл и привязать его к файловому указателю. Для открытия файла в си на чтение используется команда
Имя указателя на файл= fopen("путь к файлу", "r");
Например следующая команда
fin = fopen("C:\Users\user\Desktop\data.txt", "r");
откроет файл data.txt, находящийся на рабочем столе по пути C:\Users\user\Desktop Чтобы узнать путь к файлу можно выбрать файл мышью нажать на правую кнопку мыши и выбрать свойства файла. В разделе Расположение будет указан путь к файлу. Обратите внимание , что в си путь указывается с помощью двух слешей.
После работы с файлом в си , необходимо его закрыть с помощью команды
fclose(имя указателя на файл)

Считывание информации из текстового файла в Си

Чтобы можно было считывать русские символы из файла, необходимо настроить работу с Кириллицей с помощью команды
setlocale(LC_ALL, "Russian");

При этом необходимо в начале программы подключить #include

Оператор fscanf()

Для считывания слова из файла в си используется команда fscanf(). Эта команда аналогична команде ввода информации с клавиватуры в си scanf() только первый параметр это указатель на файл
fscanf(указатель на файл,"%формат ввода данных1% форматввода данных2…",&перменная1,&переменная2…);
Например команда
fscanf(fin,"%d%d%d",&a,&b,&c);
считает из файла, который привязан к указателю на файл fin строку из трех целочисленных переменных
Разберем пример программы, которая считывает из текстового файла data.txt в которые записаны три столбца цифр информацию и записывает ее в массивы. Для каждого столбца информации свой массив. Подробно о работе с массивами в Си.
#include
#include
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

Построковое считывание информации из файла в СИ.Функция fgets ( )

Оператор fscanf() считывает из файла слово , т.е. до первого встречного пробела.
Чтобы считать из файла всю строку из файла в Си используется конструкция
if ( NULL != fgets (строковая переменная, длина строки, указатель на файл ) )
<
действия при считывании строки
>
Например программа на Си которая считывает две строки из файла и выводит их на экран
#include
#include
#include
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 ",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 оба эти числа и их сумму

main()
< int a;
int b;
int c;
FILE *fout;
fout = fopen("C:\Users\user\Desktop\out.txt", "w");
printf ("введите первое число ");
scanf("%d", &a);
printf ("введите второе число ");
scanf("%d", &b);
c=a+b;
fprintf(fout,"%d %d %d",a,b,c);
getch();
fclose(fout);
>

Вернуться к содержанию Перейти к уроку Ошибки в программах на си

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

Потоковая модель файлового ввода-вывода была популяризирована во многом благодаря операционной системе Unix, написанной на языке Си. Большая функциональность современных операционных систем унаследовала потоки от Unix, а многие языки семейства языков программирования Си унаследовали интерфейс файлового ввода-вывода языка Си с небольшими отличиями (например, PHP). Стандартная библиотека C++ отражает потоковую концепцию в своём синтаксисе (смотрите iostream).

Читайте также:  Составить интервальное распределение выборки

Содержание

Открытие файла при помощи функции fopen [ править | править код ]

Файл открывается при помощи функции fopen , которая возвращает информацию потока ввода-вывода, прикреплённого к указанному файлу или другому устройству, с которого идет чтение (или в который идет запись). В случае неудачи функция возвращает нулевой указатель.

Схожая функция freopen библиотеки Си выполняет аналогичную операцию после первого закрытия любого открытого потока, связанного с её параметрами.

Они объявляются как

Функция fopen по сути представляет собой «обертку» более высокого уровня системного вызова open операционной системы Unix. Аналогично, fclose является оберткой системного вызова Unix close , а сама структура FILE языка Си зачастую обращается к соответствующему файловому дескриптору Unix. В POSIX-окружении функция fdopen может использоваться для инициализации структуры FILE файловым дескриптором. Тем не менее, файловые дескрипторы как исключительно Unix-концепция не представлены в стандарте языка Си.

Параметр mode (режим) для fopen и freopen должен быть строковый и начинаться с одной из следующих последовательностей:

режим описание начинает с..
r rb открывает для чтения начала
w wb открывает для записи (создаёт файл в случае его отсутствия). Удаляет содержимое и перезаписывает файл. начала
a ab открывает для добавления (создаёт файл в случае его отсутствия) конца
r+ rb+ r+b открывает для чтения и записи начала
w+ wb+ w+b открывает для чтения и записи. Удаляет содержимое и перезаписывает файл. начала
a+ ab+ a+b открывает для чтения и записи (создаёт файл в случае его отсутствия) конца

Значение «b» зарезервировано для двоичного режима С. Стандарт языка Си описывает два вида файлов — текстовые и двоичные — хотя операционная система не требует их различать (однако, для некоторых компиляторов, например LCC, указание ‘b’ при работе с бинарным файлом принципиально важно!). Текстовый файл — файл, содержащий текст, разбитый на строки при помощи некоторого разделяющего символа окончания строки или последовательности (в Unix — одиночный символ перевода строки
; в Microsoft Windows за символом перевода строки следует знак возврата каретки)
. При считывании байтов из текстового файла, символы конца строки обычно связываются (заменяются) с переводом строки для упрощения обработки. При записи текстового файла одиночный символ перевода строки перед записью связывается (заменяется) с специфичной для ОС последовательностью символов конца строки. Двоичный файл — файл, из которого байты считываются и выводятся в «сыром» виде без какого-либо связывания (подстановки).

При открытом файле в режиме обновления (‘+‘ в качестве второго или третьего символа аргумента обозначения режима) и ввод и вывод могут выполняться в одном потоке. Тем не менее, запись не может следовать за чтением без промежуточного вызова fflush или функции позиционирования в файле ( fseek , fsetpos или rewind ), а чтение не может следовать за записью без промежуточного вызова функции позиционирования в файле. [1]

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

Закрытие потока при помощи fclose [ править | править код ]

Функция fclose принимает один аргумент: указатель на структуру FILE потока для закрытия.

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

Чтение из потока [ править | править код ]

при помощи fgetc [ править | править код ]

Функция fgetc применяется для чтения символа из потока.

В случае успеха, fgetc возвращает следующий байт или символ из потока (зависит от того, файл «двоичный» или «текстовый», как выше обсуждалось). В противном случае, fgetc возвращает EOF . (Отдельный тип ошибок можно определить вызовом ferror или feof с указателем на файл.)

Стандартный макрос getc также определён в , успешно работая как fgetc , кроме одного: будучи макросом, он может обрабатывать свои аргументы более одного раза.

Стандартная функция getchar также определена в , она не принимает аргументов, и эквивалентна getc(stdin) .

«Ловушка» EOF [ править | править код ]

Распространённой ошибкой является использование fgetc , getc или getchar для присваивания результата переменной типа char перед сравнением его с EOF . Следующий фрагмент кода демонстрирует эту ошибку, а рядом приведён корректный вариант:

Ошибка Правильно

Нужно учитывать систему, в которой тип char , длина которого составляет 8 бит (в частности, архитектура x86), представляет 256 различных значений. getchar может возвращать любой из 256 возможных символов, а также может возвращать EOF для обозначения конца файла, значение которого не может совпадать ни с одним из значений char .

Когда результат getchar присваивается переменной типа char , которая может представить лишь 256 различных значений, происходит вынужденная потеря информации — при сжатии 257 значений в 256 «мест» происходит коллизия. Значение EOF при конвертации в char становится неотличимым от любого из остальных 256 символов. Если этот символ обнаружен в файле, код, приведённый выше, может принять его за признак конца файла, или, что ещё хуже, если тип char — беззнаковый, тогда с учётом того, что EOF — значение отрицательное, оно никогда не сможет стать равным любому беззнаковому char , и таким образом, пример выше не закончится на метке конца файла, а будет выполняться вечно, повторно печатая символ, получающийся при конвертации EOF в char .

Читайте также:  Технические характеристики мультимедийного проектора

В системах, где int и char одинакового размера [ каких? ] [ источник не указан 3263 дня ] , даже «правильный» вариант будет работать некорректно из-за сходства EOF и другого символа. Правильным вариантом обработки подобной ситуации является проверка feof и ferror после того, как getchar вернет EOF . Если feof определит, что конец файла ещё не достигнут, а ferror «сообщит», что ошибок нет, то EOF , возвращённый getchar , может считаться текущим символом. Такие дополнительные проверки делаются редко, так как большинство программистов считает, что их код никогда не будет выполняться на подобных системах с «большим char ». Другой способ состоит в использовании проверки при компиляции, что UINT_MAX > UCHAR_MAX , которая хотя бы предотвратит компиляцию на подобных системах.

при помощи fgets [ править | править код ]

Функция fgets применяется для чтения строки из потока. Считывание происходит до тех пор пока не будет достигнут конец строки (hex:0D0A, эквивалентны в листингах
) или длина строки, в которую происходит считывание. Предположим, у нас есть файл some_file.txt с текстом

в результате выполнения мы получим

Функция strlen определяет длину строки по количеству символов до ‘’ так например

fwrite [ править | править код ]

В языке программирования Си функции fread и fwrite соответственно реализуют файловые операции ввода и вывода. fread и fwrite объявлены в .

Запись в файл при помощи fwrite [ править | править код ]

fwrite определяется как

Функция fwrite записывает блок данных в поток. Таким образом запишется массив элементов array в текущую позицию в потоке. Для каждого элемента запишется size байт. Индикатор позиции в потоке изменится на число байт, записанных успешно. Возвращаемое значение будет равно count в случае успешного завершения записи. В случае ошибки возвращаемое значение будет меньше count .

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

Запись в поток при помощи fputс [ править | править код ]

Функция fputc применяется для записи символа в поток.

Параметр c «тихо» конвертируется в unsigned char перед выводом. Если прошло успешно, то fputc возвращает записанный символ. Если ошибка, то fputc возвращает EOF .

Стандартный макрос putc также определён в , работая в общем случае аналогично fputc , за исключением того момента, что будучи макросом, он может обрабатывать свои аргументы более одного раза.

Стандартная функция putchar , также определённая в , принимает только первый аргумент, и является эквивалентной putc(c, stdout) , где c является упомянутым аргументом.

Пример использования [ править | править код ]

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

Для удобства обращения информация в запоминающих устройствах хранится в виде файлов.

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

Каталог ( папка , директория ) – именованная совокупность байтов на носителе информации, содержащая название подкаталогов и файлов, используется в файловой системе для упрощения организации файлов.

Файловой системой называется функциональная часть операционной системы, обеспечивающая выполнение операций над файлами. Примерами файловых систем являются FAT (FAT – File Allocation Table, таблица размещения файлов), NTFS, UDF (используется на компакт-дисках).

Существуют три основные версии FAT: FAT12, FAT16 и FAT32. Они отличаются разрядностью записей в дисковой структуре, т.е. количеством бит, отведённых для хранения номера кластера. FAT12 применяется в основном для дискет (до 4 кбайт), FAT16 – для дисков малого объёма, FAT32 – для FLASH-накопителей большой емкости (до 32 Гбайт).

Рассмотрим структуру файловой системы на примере FAT32.

Файловая структура FAT32

Устройства внешней памяти в системе FAT32 имеют не байтовую, а блочную адресацию. Запись информации в устройство внешней памяти осуществляется блоками или секторами.

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

Кластер – объединение нескольких секторов, которое может рассматриваться как самостоятельная единица, обладающая определёнными свойствами. Основным свойством кластера является его размер, измеряемый в количестве секторов или количестве байт.

Файловая система FAT32 имеет следующую структуру.

Нумерация кластеров, используемых для записи файлов, ведется с 2. Как правило, кластер №2 используется корневым каталогом, а начиная с кластера №3 хранится массив данных. Сектора, используемые для хранения информации, представленной выше корневого каталога, в кластеры не объединяются.
Минимальный размер файла, занимаемый на диске, соответствует 1 кластеру.

Загрузочный сектор начинается следующей информацией:

  • EB 58 90 – безусловный переход и сигнатура;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 – количество байт в секторе (обычно 512);
  • 1 байт – количество секторов в кластере;
  • 2 байта – количество резервных секторов.
Читайте также:  Что обозначает смайлик ладошки

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

  • 0x10 (1 байт) – количество таблиц FAT (обычно 2);
  • 0x20 (4 байта) – количество секторов на диске;
  • 0x2С (4 байта) – номер кластера корневого каталога;
  • 0x47 (11 байт) – метка тома;
  • 0x1FE (2 байта) – сигнатура загрузочного сектора ( 55 AA ).

Сектор информации файловой системы содержит:

  • 0x00 (4 байта) – сигнатура ( 52 52 61 41 );
  • 0x1E4 (4 байта) – сигнатура ( 72 72 41 61 );
  • 0x1E8 (4 байта) – количество свободных кластеров, -1 если не известно;
  • 0x1EС (4 байта) – номер последнего записанного кластера;
  • 0x1FE (2 байта) – сигнатура ( 55 AA ).

Таблица FAT содержит информацию о состоянии каждого кластера на диске. Младшие 2 байт таблицы FAT хранят F8 FF FF 0F FF FF FF FF (что соответствует состоянию кластеров 0 и 1, физически отсутствующих). Далее состояние каждого кластера содержит номер кластера, в котором продолжается текущий файл или следующую информацию:

  • 00 00 00 00 – кластер свободен;
  • FF FF FF 0F – конец текущего файла.

Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:

  • 8 байт – имя файла;
  • 3 байта – расширение файла;

Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:

  • 8 байт – имя файла;
  • 3 байта – расширение файла;
  • 1 байт – атрибут файла:
  • 1 байт – зарезервирован;
  • 1 байт – время создания (миллисекунды) (число от 0 до 199);
  • 2 байта – время создания (с точностью до 2с):
  • 2 байта – дата создания:
  • 2 байта – дата последнего доступа;
  • 2 байта – старшие 2 байта начального кластера;
  • 2 байта – время последней модификации;
  • 2 байта – дата последней модификации;
  • 2 байта – младшие 2 байта начального кластера;
  • 4 байта – размер файла (в байтах).

В случае работы с длинными именами файлов (включая русские имена) кодировка имени файла производится в системе кодировки UTF-16. При этого для кодирования каждого символа отводится 2 байта. При этом имя файла записывается в виде следующей структуры:

  • 1 байт последовательности;
  • 10 байт содержат младшие 5 символов имени файла;
  • 1 байт атрибут;
  • 1 байт резервный;
  • 1 байт – контрольная сумма имени DOS;
  • 12 байт содержат младшие 3 символа имени файла;
  • 2 байта – номер первого кластера;
  • остальные символы длинного имени.

Далее следует запись, включающая имя файла в формате 8.3 в обычном формате.

Работа с файлами в языке Си

Для программиста открытый файл представляется как последовательность считываемых или записываемых данных. При открытии файла с ним связывается поток ввода-вывода . Выводимая информация записывается в поток, вводимая информация считывается из потока.

Когда поток открывается для ввода-вывода, он связывается со стандартной структурой типа FILE , которая определена в stdio.h . Структура FILE содержит необходимую информацию о файле.

Открытие файла осуществляется с помощью функции fopen() , которая возвращает указатель на структуру типа FILE , который можно использовать для последующих операций с файлом.

  • "r" — открыть файл для чтения (файл должен существовать);
  • "w" — открыть пустой файл для записи; если файл существует, то его содержимое теряется;
  • "a" — открыть файл для записи в конец (для добавления); файл создается, если он не существует;
  • "r+" — открыть файл для чтения и записи (файл должен существовать);
  • "w+" — открыть пустой файл для чтения и записи; если файл существует, то его содержимое теряется;
  • "a+" — открыть файл для чтения и дополнения, если файл не существует, то он создаётся.

Возвращаемое значение — указатель на открытый поток. Если обнаружена ошибка, то возвращается значение NULL .

Функция fclose() закрывает поток или потоки, связанные с открытыми при помощи функции fopen() файлами. Закрываемый поток определяется аргументом функции fclose() .

Возвращаемое значение: значение 0, если поток успешно закрыт; константа EOF , если произошла ошибка.

Чтение символа из файла:

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

Запись символа в файл:

Аргументами функции являются символ и указатель на поток типа FILE . Функция возвращает код считанного символа.

Функции fscanf() и fprintf() аналогичны функциям scanf() и printf() , но работают с файлами данных, и имеют первый аргумент — указатель на файл.

Функции fgets() и fputs() предназначены для ввода-вывода строк, они являются аналогами функций gets() и puts() для работы с файлами.

Символы читаются из потока до тех пор, пока не будет прочитан символ новой строки ‘
’ , который включается в строку, или пока не наступит конец потока EOF или не будет прочитано максимальное символов. Результат помещается в указатель на строку и заканчивается нуль- символом ‘’ . Функция возвращает адрес строки.

Результат выполнения — 2 файла

Работа с файлами в C++ описана здесь.

Комментировать
0 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
Adblock detector