Как читать структуры из файла c
Перейти к содержимому

Как читать структуры из файла c

  • автор:

Чтение структур

Для того чтобы прочитать структуру целиком, используется функция 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 имеет следующую структуру.
Файловая система 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-ричного вида файла (см. комменты)
скриншот 16-ричного вида файла (см. комменты)

  • писать и читать только string.c_str() в бинарные файлы, сведя задачу к предыдущей ссылке (но тогда не нужны и string , а можно делать классически на char * );
  • всё же отказаться от бинарных, а ограничиться текстовыми файлами и парсить полученные через getline строки;
  • предусмотреть в формате файла одновременное сохранение длины строковых данных объекта string .

В последнем случае имеем примерно такой подход (проверен не на структурах, а на паре строк).

Программа для записи набора string в бинарный файл:

Потом читаем это (возможно, с точностью до кодировки):

В моей консоли Visual Studio 2015 обе программки сработали. Итак, если строка string является полем структуры, разницы в подходах нет.

P.P.S. Ну и, раз пошла такая пьянка, теперь разрешим строкам string в массиве структур иметь произвольную длину и содержать пробелы (по умолчанию чтение string из файлового потока прервётся на первом пробельном символе), а сохранять всё будем в текстовом файле, и читать из него же.

Чтобы всё работало, нам пришлось переписать оператор >> для своей структуры.

Программа создаст и затем прочитает такой файл:

При чтении код сам избавится от лишних пробелов в строках между лексемами, следующими после числа.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *