Чтение структур
Для того чтобы прочитать структуру целиком, используется функция fread(). Она имеет следующий синтаксис:
За исключением имени функции эта инструкция полностью совпадает с записью функции fwrite(). Программа, в которой из файла считывается структура CD, приведена в Листинге12.6. Для чтения данных используется цикл while:
while (fread(&disc, sizeof(disc), 1, fp) == 1)
Функция fread() возвращает значение, соответствующее количеству успешно прочитанных структур. Так как в аргументе функции мы указали, что читать следует по одной структуре, функция возвращает значение 1. Цикл while будет выполняться до тех пор, пока считывание структур с диска проходит успешно. Если чтение структуры становится невозможным, например потому, что достигнут конец файла, функция возвращает значение 0, и выполнение цикла прекращается.
Листинг 12.6. Чтение структуры CD с диска.
printf(«Введите имя файла, который
if ((fp = fopen(filename, «r»)) == NULL)
printf(«Невозможно открыть файл
while (fread(&disc, sizeof(disc), 1, fp) == 1)
В табл. 12.1 собраны все описанные способы ввода и вывода данных и показаны значения, которые возвращает каждая функция при невозможности продолжения чтения или записи данных.
Таблица 12.1. Функции ввода в файл и вывода из файла.

Чтение в массив
Во всех программах, приведенных до настоящего момента в качестве примера, выполнялось чтение данных из файла и отображение вводимой информации на экране. Однако если считывать данные в переменные, с ними можно выполнять любые операции, например, использовать их для записи в массив.
В Листинге 12.7 приведен текст программы, осуществляющей чтение информации из файла, содержащего данные о коллекции компакт-дисков, в массив структур CD (предполагается, что их количество не превышает20). Индекс используется для того, чтобы каждая считанная из файла структура сохранялась в отдельном элементе массива disc. После того как очередная структура прочитана и выведена на экран, стоимость очередного диска добавляется к сумме, отражающей общую стоимость коллекции, а значение индекса и счетчика увеличивается за счет выполнения следующих инструкций:
total = total + disc[index].cost;
Если бы нас интересовала только информация об общей стоимости и количестве экземпляров коллекции, можно было бы читать данные в структурную переменную, не используя массив, и просто подсчитывать значения переменных total и count. Однако если данные будут считаны в массив, вы сможете произвольным образом обращаться к структурам и печатать любую информацию.
Заметьте, что запрос о вводе имени файла в программе повторяется до тех пор, пока не будет введено имя файла, который действительно можно открыть.
C++. Примеры использования средств C++ для работы с файлами
Примеры использования средств C++ для работы с файлами
В теме приводятся примеры использования файловой системы C++ для:
- чтения информации из файлов;
- записи информации в файлы.
Содержание
- 1. Функция, читающая строки из клавиатуры и записывающая их в файл
- 2. Функция, которая читает текстовый файл и выводит его содержимое на экран
- 3. Пример бесформатного ввода/вывода. Копирование одного файла в другой
- 4. Пример бесформатного ввода/вывода. Копирование одного файла в другой. Функция put()
- 5. Пример функции записывающей структурную переменную в файл
- 6. Пример чтения структурной переменной из файла
- 7. Пример чтения/записи массива структур в файл. Функции write() , read()
- 8. Пример записи/чтения массива чисел типа double
- 9. Пример чтения из файла строк. Функция getline()
- 10. Пример чтения строк из файла. Функции getline() + eof()
Поиск на других ресурсах:
1. Функция, читающая строки из клавиатуры и записывающая их в файл
После вызова функции Example1() будет создан файл «myfile.txt» , в котором будут записаны строки, введенные с клавиатуры.
Результат работи программы:
2. Функция, которая читает текстовый файл и выводит его содержимое на экран
Функция Example2() читает содержимое файла filename , имя которого есть входящим параметром функции.
Результат работи программы отображает содержимое файла «myfile.txt» , созданного в п.1 этой темы
3. Пример бесформатного ввода/вывода. Копирование одного файла в другой
В примере реализована функция Example3() , которая выполняет копирование файлов в двоичном (бинарном) формате. Функция получает два параметра. Первый параметр типа const char* есть имя файла-источника. Второй параметр типа const char* есть имя файла-назначения.
Функция реализует посимвольное копирование. Для получения символа из файла-источника используется функция get() .
Вызов функции Example3() из функции main() может быть следующим:
После выполнения функции Example3() будет создан файл «myfile2.txt» , который будет копией файла «myfile.txt» .
4. Пример бесформатного ввода/вывода. Копирование одного файла в другой. Функция put()
Функция Example4() из данного примера работает также как и предыдущая, только вместо вывода в поток << используется функция put() . Также, с помощью функции is_open() выполняется проверка на корректность открытия файла.
5. Пример функции записывающей структурную переменную в файл
По данному примеру можно реализовывать собственные функции, которые будут записывать структуры или классы в файл.
Реализована функция Example5() , которая выполняет запись структурной переменной типа BOOK в файл, имя которого есть входящим параметром. Функция Example5() использует функцию write() для записи. Файл открывается в двоичном формате ( ios::binary ).
6. Пример чтения структурной переменной из файла
Данный пример есть продолжением предыдущего примера из пункта 5. В примере в функции Example6() заполняется значение структурной переменной типа BOOK . Полученное значение формируется как входящий параметр-ссылка на тип BOOK . Также функция получает параметром имя файла для чтения. Для чтения структурной переменной используется функция read() .
Результат работы программы
8. Пример записи/чтения массива чисел типа double
- запись в файл массива M чисел типа double функцией write() ;
- чтение из файла массива чисел типу double функцией read() .
Файл открывается в двоичном формате.
Результат работи программы:
9. Пример чтения из файла строк. Функция getline()
В функции Example9() реализуется построчное чтение из файла с помощью функции getline() . Имя файла задается входящим параметром filename . Строки в файле состоят из набора слов, разделенных символом «пробел».
10. Пример чтения строк из файла. Функции getline() + eof()
В примере реализована функция Example10() , которая выполняет чтение строк из файла. Файл открывается в текстовом формате. Имя файла задается входящим параметром функции. Определение конца файла выполняется с помощью функции eof() .
Как читать структуры из файла c
if (outfile == NULL)
fprintf (stderr, «\nError opend file\n» );
fwrite (&input1, sizeof ( struct person), 1, outfile);
fwrite (&input2, sizeof ( struct person), 1, outfile);
printf ( «contents to file written successfully !\n» );
printf ( «error writing file !\n» );
struct person input;
if (infile == NULL)
fprintf (stderr, «\nError opening file\n» );
while ( fread (&input, sizeof ( struct person), 1, infile))
printf ( «id = %d name = %s %s\n» , input.id,
Файловая структура FAT32
Файловая система 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 ).
- 00 00 00 00 – кластер свободен;
- FF FF FF 0F – конец текущего файла.
- 8 байт – имя файла;
- 3 байта – расширение файла;
- 8 байт – имя файла;
- 3 байта – расширение файла;
- 1 байт – атрибут файла:

- 1 байт – зарезервирован;
- 1 байт – время создания (миллисекунды) (число от 0 до 199);
- 2 байта – время создания (с точностью до 2с):

- 2 байта – дата создания:

- 2 байта – дата последнего доступа;
- 2 байта – старшие 2 байта начального кластера;
- 2 байта – время последней модификации;
- 2 байта – дата последней модификации;
- 2 байта – младшие 2 байта начального кластера;
- 4 байта – размер файла (в байтах).
Как читать структуры из файла c
БлогNot. Структура со строками string и файловые чтение/запись массива таких структур
Структура со строками string и файловые чтение/запись массива таких структур
В отличие от этого примера, используем в структурном типе данных более удобные в обращении и современные строки string и файловые потоки вместо классических си-строк char * и файлов из <cstdio> . Лекции по всем этим темам можно найти в оглавлении.
В итоге должна получиться программка, которая покажет непосредственное задание значений полям структурной переменной и ввод значений полей с консоли, а также запись файла структур и последующее его контрольное чтение. Проверяться она будет в консоли Visual Studio 2015, проект создан как вот здесь.
В начале файла укажем нужные библиотеки и директивы, в комментариях написано, для чего какая служит:
Опишем структурный тип данных, включающий в себя идентификатор (номер) записи, две строки для хранения имени и даты рождения, а также вещественное поле money для хранения, например, зарплаты:
Мы не указываем какие-либо ограничения на длину строки, потому что сами будем управлять этим.
Так как программа может завершиться тремя способами — нормально, при ошибке записи файла и при ошибке его чтения, напишем функцию error с аргументом n (номер ошибки), которая будет за это отвечать. Ошибка номер ноль, как принято в C++, будет означать нормальное завершение. Вообще такую «общую точку выхода» зачастую полезно делать в процедурно-ориентированном коде:
Функция для ввода данных с консоли input получает аргументами адрес структуры a , куда нужно заносить данные (это может быть, в том числе, и адрес элемента массива структур) и идентификатор записи i , остальные поля записи она запрашивает у пользователя.
В реальности стоило бы снабдить код большим количеством проверок корректности данных и вводом их в некую буферную запись, откуда потом скорректированные данные могут быть скопированы в массив или в файл.
Также обратите внимание, что мы не должны «резать» поля структуры кодом вроде
но с отдельной буферной строкой имели бы на это право, конечно же, прежде, чем копировать её в запись, предназначенную для постоянного хранения.
Со всеми этими оговорками, простейшая функция ввода записи получилась такой:
Функция output , соответственно, выводит в консоль поля записи a , переданной аргументом:
При корректных данных должны получиться столбцы правильной ширины.
Главной программе осталось русифицировать консоль и создать массив записей, для простоты предусмотрим там всего 2 элемента:
Первый элемент с id , равным нулю, зададим программно, а второй введём с консоли:
Откроем файл notes.dat для записи и поместим туда данные, заодно печатая их в консоль:
Обратите внимание, что применение sizeof к составному объекту string некорректно, приходится писать в бинарный файл отдельными полями.
После закрытия файла, откроем его вновь для чтения и покажем прочитанные в цикле записи на экране, после чего можно сделать нормальный выход из программы:
Вы понимаете, что наш файл — двоичный, и открывать его текстовым редактором бессмысленно.
Вот лог работы нашей программы:
скриншот 16-ричного вида файла (см. комменты)
- писать и читать только string.c_str() в бинарные файлы, сведя задачу к предыдущей ссылке (но тогда не нужны и string , а можно делать классически на char * );
- всё же отказаться от бинарных, а ограничиться текстовыми файлами и парсить полученные через getline строки;
- предусмотреть в формате файла одновременное сохранение длины строковых данных объекта string .
В последнем случае имеем примерно такой подход (проверен не на структурах, а на паре строк).
Программа для записи набора string в бинарный файл:
Потом читаем это (возможно, с точностью до кодировки):
В моей консоли Visual Studio 2015 обе программки сработали. Итак, если строка string является полем структуры, разницы в подходах нет.
P.P.S. Ну и, раз пошла такая пьянка, теперь разрешим строкам string в массиве структур иметь произвольную длину и содержать пробелы (по умолчанию чтение string из файлового потока прервётся на первом пробельном символе), а сохранять всё будем в текстовом файле, и читать из него же.
Чтобы всё работало, нам пришлось переписать оператор >> для своей структуры.
Программа создаст и затем прочитает такой файл:
При чтении код сам избавится от лишних пробелов в строках между лексемами, следующими после числа.