В приведенном выше примере самым "длинным" является вариант "b ": для него требуется 23 байта (21 байт для строки и 2 байта для целого числа). Для вариантов "n " и "m " требуется 4 и 5 байт соответственно (см. таблицу).
name, publisher item Вариантная часть
Бинарные файлы
Бинарные файлы хранят информацию в том виде, в каком она представлена в памяти компьютера, и потому неудобны для человека. Заглянув в такой файл, невозможно понять, что в нем записано; его нельзя создавать или исправлять вручную - в каком-нибудь текстовом редакторе - и т.п. Однако все эти неудобства компенсируются скоростью работы с данными.
Кроме того, текстовые файлы относятся к структурам последовательного доступа, а бинарные - прямого. Это означает, что в любой момент времени можно обратиться к любому, а не только к текущему элементубинарного файла .
Типизированные файлы
Переменные структурированных типов данных (кроме строкового) невозможно считать из текстового файла. Например, если нужно ввести из текстового файла данные для наполнения записи toy информацией об имеющихся в продаже игрушках (название товара, цена товара и возрастной диапазон, для которого игрушка предназначена):
age: set of 0..18; {в файле задано границами}
то придется написать следующий код:
c: char; i,j,min,max: integer;
a: array of toy;
begin assign(f,input); reset(f);
for i:=1 to 100 do if not eof(f)
then with a[i] do
begin readln(f,name,price,min,max); age:=;
for j:= min to max do age:=age+[j];
Как видим, такое поэлементное считывание весьма неудобно и трудоемко.
Выход из этой ситуации предлагают типизированные файлы - их элементы могут относиться к любому базовому или структурированному типу данных. Единственное ограничение: все элементы должны быть одного и того же типа. Это кажущееся неудобство является
непременным условием для организации прямого доступа к элементам бинарного файла : как и в случае массивов, если точно известна длина каждого компонента структуры, то адрес любого компонента может быть вычислен по очень простой формуле:
<начало_структуры> + <номер_компонента>*<длина_компонента>
Описание типизированных файлов
В разделе var файловые переменные, предназначенные для работы стипизированными файлами , описываются следующим образом:
var <файловая_перем>: file of <тип_элементов_файла>;
Никакая файловая переменная не может быть задана константой.
Назначение типизированного файла
С этого момента и до конца раздела под словом "файл" мы будем подразумевать "бинарный типизированный файл " (разумеется, если специально не оговорено иное).
Команда assign(f,"<имя_файла>"); служит для установления связи между файловой переменнойf и именем того файла, за работу с которым эта переменная будет отвечать.
Строка "<имя_файла> " может содержать полный путь к файлу. Если путь не указан, файл считается расположенным в той же директории, что и исполняемый модуль программы.
Открытие и закрытие типизированного файла
В зависимости от того, какие действия ваша программа собирается производить с открываемым файлом, возможно двоякое его открытие:
reset(f); - открытие файла для считывания из него информации и одновременно длязаписи в него (если такого файла не существует, попытка открытия вызовет ошибку). Эта же команда служит для возвращения указателя на начало файла;
rewrite(f); - открытие файла длязаписи в него информации; если такого файла не существует, он будет создан; если файл с таким именем уже есть, вся содержавшаяся в нем ранее информация исчезнет.
Закрываются типизированные файлы процедуройclose(f) , общей для всех типов файлов.
Считывание из типизированного файла
Чтение из файла, открытого для считывания, производится с помощью команды read() . В скобках сначала указывается имя файловой переменной, а затем - список ввода1) :
Вводить из файла можно только переменные соответствующего объявлению типа, но этот тип данных может быть и структурированным. Cкажем, если вернуться к примеру, приведенному в начале п. "Типизированные файлы ", то станет очевидным, что использованиетипизированного файла вместо текстового позволит значительно сократить текст программы:
type toy = record name: string; price: real;
age: set of 0..18; {задано границами}
var f: file of toy;
a: array of toy; begin
assign(f,input);
for i:=1 to 100 do
if not eof(f) then read(f,a[i]); close(f);
Поиск в типизированном файле
Уже знакомая нам функция eof(f:file):boolean сообщает о достигнутом конце файла. Все остальные функции "поиска конца" (eoln() ,seekeof() иseekeoln() ), свойственные текстовым файлам, нельзя применять к файламтипизированным .
Зато существуют специальные подпрограммы, которые позволяют работать с типизированными файлами как со структурами прямого доступа:
1. Функция filepos(f:file):longint сообщит текущее положение указателя в файлеf . Если он указывает на самый конец файла, содержащегоN элементов, то эта функция выдаст результатN . Это легко объяснимо: элементы файла нумеруются начиная с нуля, поэтому последний элемент имеет номер N-1 . А номерN принадлежит, таким образом, "несуществующему" элементу - признаку конца файла.
2. Функция filesize(f:file):longint вычислит длину файлаf .
3. Процедура seek(f:file,n:longint) передвинет указатель в файлеf на началозаписи с номеромN . Если окажется, чтоn больше фактической длины файла, то указатель будет передвинут и за реальный конец файла.
4. Процедура truncate(f:file) обрежет "хвост" файлаf : все элементы начиная с текущего и до конца файла будут из него удалены. На самом же деле произойдет лишь переписывание признака "конец файла" в то место, куда указывал указатель, а физически "отрезанные" значения останутся на прежних местах - просто они станут "бесхозными".
Запись в типизированный файл
Сохранять переменные в файл, открытый для записи , можно при помощи командыwrite() . Так же как и в случае считывания, первой указывается файловая переменная, а за ней - список вывода:
write(f,a,b,c); - записать в файлf (предварительно открытый длязаписи командамиrewrite(f) илиreset(f) ) переменныеa ,b ,c .
Выводить в типизированный файл можно только переменные соответствующего описанию типа данных. Неименованные и нетипизированные константы нельзя выводить в
типизированный файл.
Типизированные файлы рассматриваются как структуры одновременно и прямого, и последовательного доступа. Это означает, чтозапись возможна не только в самый конец файла, но и в любой другой его элемент. Записываемое значение заместит предыдущее значение в этом элементе (старое значение будет "затерто").
Например, если нужно заместить пятый элемент файла значением, хранящимся в переменной а , то следует написать следующий отрывок программы:
seek(f,5); {указатель будет установлен на начало 5-го элемента}
write(f,a); {указатель будет установлен на начало 6-го элемента}
Файлам. При этом с точки зрения технической реализации на уровне аппаратуры, текстовые файлы являются частным случаем двоичных файлов, и, таким образом, в широком значении слова под определение «двоичный файл» подходит любой файл.
Часто двоичными файлами называют исполняемые файлы и сжатые данные , однако некорректно так ограничивать это понятие.
Визуализация
Для наглядного представления двоичного файла он разбивается на куски равного размера, представляемые в виде чисел, записываемых, обычно, в шестнадцатеричной системе , иногда в восьмеричной , двоичной или десятичной . Означенный размер куска может быть равен одному октету , а также двум или четырём (в случае разбиения на куски по несколько октетов применяется порядок байтов , принятый на используемой платформе). Зависимость диапазона представляемых чисел от размера куска показана в таблице:
октетов | кол-во бит | шестнадцатеричное | восьмеричное | десятичное беззнаковое |
десятичное знаковое |
---|---|---|---|---|---|
1 | 8 | 00 … FF |
000 … 377 |
0 … 255 |
-128 … 127 |
2 | 16 | 0000 … FFFF |
000000 … 177777 |
0 … 65535 |
-32768 … 32767 |
4 | 32 | 00000000 … FFFFFFFF |
00000000000 … 37777777777 |
0 … 4294967295 |
-2147483648 … 2147483647 |
Нередко, помимо числовых значений байт, выводятся так же символы кодовой страницы , например печатными ASCII-символами справа) начала PNG -файла логотипа Википедии:
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| 00000010 00 00 00 87 00 00 00 a0 08 03 00 00 00 11 90 8f |................| 00000020 b6 00 00 00 04 67 41 4d 41 00 00 d6 d8 d4 4f 58 |.....gAMA.....OX| 00000030 32 00 00 00 19 74 45 58 74 53 6f 66 74 77 61 72 |2....tEXtSoftwar| 00000040 65 00 41 64 6f 62 65 20 49 6d 61 67 65 52 65 61 |e.Adobe ImageRea| 00000050 64 79 71 c9 65 3c 00 00 03 00 50 4c 54 45 22 22 |dyq.e<....PLTE""| 00000060 22 56 56 56 47 47 47 33 33 33 30 30 30 42 42 42 |"VVVGGG333000BBB| 00000070 4b 4b 4b 40 40 40 15 15 15 4f 4f 4f 2c 2c 2c 3c |KKK@@@...OOO,<| 00000080 3c 3c 3e 3e 3e 3a 39 39 04 04 04 1d 1d 1d 35 35 |<<>>>:99......55| 00000090 35 51 50 50 37 37 37 11 11 11 25 25 25 0d 0d 0d |5QPP777...%%%...| 000000a0 27 27 27 1a 1a 1a 38 38 38 2a 2a 2a 08 08 08 20 |"""...888***... | 000000b0 20 20 17 17 17 2e 2e 2e 13 13 13 bb bb bb 88 88 | ..............|
Инструменты
Для визуализации
- debug (в Microsoft Windows , частично)
- hexdump (в GNU/Linux и т. п.)
Для редактирования
Литература
- Webster’s New World Dictionary of Computer Terms, 4th. Ed, Prentice Hall, NY, 1992. ISBN 0-671-84651-5
- Леонтьев Б. К. Форматы файлов Microsoft Windows XP: Справочник, М.: ЗАО «Новый издательский дом», 2005. ISBN 5-9643-0059-6
Wikimedia Foundation . 2010 .
Смотреть что такое "Бинарный файл" в других словарях:
Сущ., м., употр. сравн. часто Морфология: (нет) чего? файла, нет? файлу, (вижу) что? файл, чем? файлом, о чём? о файле; мн. что? файлы, (нет) чего? файлов, чем? файлам, (вижу) что? файлы, чем? файлами, о чём? о файлах 1. Файлом называется массив… … Толковый словарь Дмитриева
Двоичный (бинарный) файл в широком смысле: последовательность произвольных байтов. Название связано с тем, что байты состоят из бит, то есть двоичных (англ. binary) цифр. В узком смысле слова двоичные файлы противопоставляются текстовым файлам.… … Википедия
Двоичный (бинарный) файл в широком смысле: последовательность произвольных байтов. Название связано с тем, что байты состоят из бит, то есть двоичных (англ. binary) цифр. В узком смысле слова двоичные файлы противопоставляются… … Википедия
конфигурационный файл - Бинарный или текстовый файл, содержащий информацию, которая определяет поведение приложения, компьютера или сетевого устройства. Тематики сети вычислительные EN configuration file … Справочник технического переводчика
У этого термина существуют и другие значения, см. IPA (значения). .IPA формат архивных файлов приложений от Apple для iPhone, iPod Touch и iPad. Файлы с данным расширением хранятся в магазине App Store и загружаются с помощью iTunes для… … Википедия
Эта статья или раздел нуждается в переработке. В Паскале нет модулей, ООП и прочих новомодных веяний. Описание расширений должно присутствовать только в статьях о соответ … Википедия
Pascal Семантика: процедурный Тип исполнения: компилятор Появился в: 1970 г. Автор(ы): Никлаус Вирт Паскаль (англ. Pascal) высокоуровневый язык программирования общего назначения. Один из наиболее известных языков программирования, широко… … Википедия
Gopher Название: Gopher Порт/ID: 70/TCP Спецификация: RFC 1436 Основные реализации (клиенты): Mozilla Firefox, Microsoft Windows: IE 5.x, IE 6 (ограничено MS) Gopher сетевой протокол распределённого поиска и передачи документов, бывший широко рас … Википедия
Название: Gopher Порт/ID: 70/TCP Спецификация: RFC 1436 Основные реализации (клиенты): Mozilla Firefox, Microsoft Windows: Internet Explorer 5.x, Internet Explorer 6 (ограничено MS) Gopher сетевой протокол распределённого поиска и передачи… … Википедия
- / * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Примечание: Поскольку расширение имени файла может быть любым, представленный список не является полным … Википедия
Рассматриваемые нами до этого времени примеры демонстрировали форматированный ввод/вывод информации в файлы. Форматированный файловый ввод/вывод чисел целесообразно использовать только при их небольшой величине и малом количестве, а также при необходимости обеспечения возможности просмотра файлов не программными средствами. В противном случае, конечно, гораздо эффективнее использовать двоичный ввод/вывод, при котором числа хранятся таким же образом, как в ОП компьютера, а не в виде символьных строк. Напомню, что целочисленное (int) или вещественное (float) значение занимает в памяти 4 байта, значение типа double – 8 байт, а символьное значение типа char - 1 байт. Например, число 12345 в текстовом (форматированном) файле занимает 5 байт, а в бинарном файле – 4 байта.
Бинарные файлы , т.е. файлы, в которых информация хранится во внутренней форме представления, применяются для последующего использования программными средствами, их невозможно просматривать не программными средствами. Преимущество бинарных файлов состоит в том, что, во-первых, при чтении/записи не тратится время на преобразование данных из символьной формы представления во внутреннюю и обратно, а во-вторых, при этом не происходит потери точности вещественных чисел. Как в случае форматированного ввода/вывода, так и в случае бинарного ввода/вывода для "правильной" обработки информации из файла необходимо знать какие типы данных, каким образом и в какой последовательности записаны в бинарный файл, тем более, что просмотр бинарного файла с помощью текстового редактора ничего не даст.
Рассмотрим пример, демонстрирующий запись целочисленных элементов динамического массива в бинарный файл и чтение их из данного файла.
#include
#include
#include
using namespace std;
cout << "Vvedite kol-vo elementov celochisl. massiva: "; cin >> N;
int *mas = new int [N];
for(i=0; i cout << " Vvedite " << i << "-i element: "; cin >> mas[i]; cout << "\nIdet zapis dannyh v fail..." << endl; ofstream fout("c:\\os\\bin.dat", ios::binary);
//созд. вых. бинарного потока if(!fout) { cout << "\n Oshibka otkrytiya faila!"; getch(); return 1; }
fout.write(reinterpret_cast fout.close();
//закрытие потока cout << "Dannye uspeshno zapisany!" << endl; for(i=0; i ifstream fin("c:\\os\\bin.dat", ios::binary); //создание потока для чтения файла if(!fin) { cout << "\n Oshibka otkrytiya faila!"; getch(); return 1; } cout << "Fail sodergit:" << endl; fin.read(reinterpret_cast for(i=0; i getch(); return 0; Особое внимание в данной программе надо уделить использованию функций write() (метод класса ofstream) и read() (метод класса ifstream). Эти функции думают о данных в терминах байтов и предназначены для переноса определённого количества байт из буфера данных в файл и обратно. Параметрами этих функций являются адрес буфера и его длина в байтах. Функция write() предназначена для записи в файл указанного во втором параметре числа байт из указанного в первом параметре адреса
буфера данных, а функция read() предназначена для считывания данных из файла. Здесь необходимо отметить, что эти функции работают с буфером данных только типа char. В связи с этим, в данной программе мы использовали оператор reinterpret_cast<>
, который преобразует буфер наших данных типа int (mas) в буфер типа char. Необходимо помнить, что приведение типа с помощью оператора
reinterpret_cast ofstream fout(filename, ios::app | ios::binary); fout.write(reinterpret_cast Теперь необходимо обсудить второй параметр рассматриваемых функций. В данной программе, в качестве второго параметра мы использовали выражение N*sizeof(int), с помощью которого вычислили количество байт. Например, если у нас 5 целочисленных элементов массива, то число байт будет равно 20. Функция sizeof() возвращает количество байт, отводимое под указанный в качестве параметра тип данных. Например, sizeof(int
) вернёт 4. Итак, приведённая в этом примере программа позволяет записать в файл bin.dat данные в бинарном виде и считывать их из этого бинарного файла. Причём после считывания эти данные приводятся к типу int, приобретают структуру массива и с ними можно производить любые операции. Теперь, представим себе, что необходимо написать программу позволяющую считывать данные из файла bin.dat, причём мы знаем только то, что в данном файле записаны элементы целочисленного массива в бинарном виде. Количество записанных элементов (N) нам не известно
. При создании программы мы не имеем права использовать константный массив, т.е. выделять память под него на этапе создания программы. Это приведет к ошибочному результату. Поскольку слишком малое значение N приведёт к тому, что считаются не все элементы массива, а слишком большое значение N приведёт к заполнению лишних ячеек случайными значениями. Рассмотрим, пример программы, позволяющей считывать из бинарного файла элементы целочисленного массива, путём динамического выделения памяти, и для доказательства реалистичности считынных данных вычислять их сумму. #include #include #include using namespace std; int N, i, sum=0, dfb; //dfb - длина файла в байтах ifstream fin("c:\\os\\bin.dat", ios::binary
); if(!fin) { cout << "Oshibka otkrytiya faila!"; getch(); return 1; } fin.seekg(0, ios::end);
//устанавливаем позицию чтения на конец файла (от конца 0 байт) dfb = fin.tellg();
//получаем значение позиции конца файла (в байтах) N=dfb/4;
//зная, что целое число занимает 4 байта, вычисляем кол-во чисел int *arr = new int [N];
//создаём динамический массив fin.seekg(0, ios::beg);
//перед чтением данных, перемещаем текущую позицию на начало файла fin.read(reinterpret_cast cout << "Iz faila schitano " << N << " elementov:" << endl; for(i=0; i for(i=0; i cout << "\n Ih summa = " << sum; getch(); return 0; Рассмотрим детально данную программу, в которой мы активно использовали функции seekg() и tellg(), являющиеся методами класса ifstream. Здесь необходимо отметить, что с любым файлом при его открытии связывается так называемая текущая позиция чтения или записи
. Когда файл открывается для чтения, эта позиция по умолчанию устанавливается на начало файла. Но достаточно часто бывает нужно контролировать позицию вручную, чтобы иметь возможность читать и писать, начиная с произвольного места файла. Функции seekg() и tellg() позволяют устанавливать и проверять текущий указатель чтения, а функции seekp() и tellp() – выполнять те же действия для указателя записи. Метод seekg(1_параметр, 2_параметр) перемещает текущую позицию чтения из файла на указанное в 1_параметре число байт относительно указанного во 2_параметре места. 2_параметр может принимать одно из трёх значений: ios::beg – от начала файла; ios::cur – от текущей позиции; ios::end – от конца файла. Здесь beg, cur и end – являются константами, определёнными в классе ios, а символы:: означают операцию доступа к этому классу. Например, оператор fin.seekg(-10, ios::end);
позволяет установить текущую позицию чтения из файла за 10 байтов до конца файла. Теперь вернёмся к описанию работы программы. Исходя из того, что нам не известно количество чисел записанных в файл, вначале необходимо узнать число чисел. Для этого, с помощью fin.seekg(0, ios::end);
мы перемещаемся в конец файла и посредством функции tellg() возвращаем в переменную dfb длину файла в байтах. Функция tellg() возвращает текущую позицию указателя в байтах. Так как длина одного целого числа в байтах нам известна (4 байта), нетрудно вычислить количество записанных в файл чисел, зная длину файла в байтах (N=dfb/4;
). Узнав количество чисел, создаём динамический массив и перемещаемся в начало файла для того, чтобы начать считывание данных с помощью функции read(). После того, как указанное нами число байт данных (dfb) перенесено в буфер данных (arr), считанные таким образом данные приобретают структуру массива и становятся полностью пригодны для каких укодно операций и преобразований. Специально для таких случаев существуют записи с вариантной частью
. В разделе var
запись с вариантной частью
описывают так: var <имя_записи>: record <поле1>: <тип1>;
[<поле2>: <тип2>;]
[...]
case <поле_переключатель>: <тип> of
<варианты1>: (<поле3>: <тип3>;
<поле4>: <тип4>;
...);
<варианты2>: (<поле5>: <тип5>;
<поле6>: <тип6>;
...);
[...]
end; Невариантная часть
записи
(до ключевого слова case
) подчиняется тем же правилам, что и обычная запись
. Вообще говоря, невариантная часть может и вовсе отсутствовать. Вариантная часть
начинается зарезервированным словом case
, после которого указывается то поле
записи
, которое в дальнейшем будет служить переключателем. Как и в случае обычного оператора case
, переключатель обязан принадлежать к одному из перечислимых типов
данных (см. лекцию 3). Список вариантов может быть константой, диапазоном или объединением нескольких констант или диапазонов. Набор полей
, которые должны быть включены в структуру записи
, если выполнился соответствующий вариант, заключается в круглые скобки. Пример
. Для того чтобы описать содержимое библиотеки, необходима следующая информация: Графы "Название" и "Издательство" являются общими для всех трех вариантов, а остальные поля
зависят от типа печатного издания. Для реализации этой структуры воспользуемся записью с вариантной частью
: type biblio = record
name,publisher: string;
case item: char of
"b": (author: string; year: 0..2004);
"n": (data: date);
"m": (year: 1700..2004;
month: 1..12;
number: integer);
end; В зависимости от значения поля
item
, в записи
будет содержаться либо 4, либо 5, либо 6 полей
. Количество байтов, выделяемых компилятором под запись с вариантной частью
, определяется самым "длинным" ее вариантом. Более "короткие" наборы полей
из других вариантов занимают лишь некоторую часть выделяемой памяти. В приведенном выше примере самым "длинным" является вариант " b
": для него требуется 23 байта (21 байт для строки и 2 байта для целого числа). Для вариантов " n
" и " m
" требуется 4 и 5 байт соответственно (см. таблицу). Бинарные файлы
хранят информацию в том виде, в каком она представлена в памяти компьютера, и потому неудобны для человека. Заглянув в такой файл
, невозможно понять, что в нем записано; его нельзя создавать или исправлять вручную - в каком-нибудь текстовом редакторе - и т.п. Однако все эти неудобства компенсируются скоростью работы с данными. Кроме того, текстовые файлы
относятся к структурам последовательного доступа
, а бинарные
- прямого. Это означает, что в любой момент времени можно обратиться к любому, а не только к текущему элементу Вся информация хранится в компьютере в виде 0 и 1, т. е. в двоичном виде. Двоичные файлы отличаются от текстовых только методами работы с ними. Например, если мы записываем в текстовый файл цифру «4», то она записывается как символ, и для ее хранения нужен один байт. Соответственно и размер файла будет равен одному байту. Текстовый файл, содержащий запись: «145687», будет иметь размер шесть байт. Если же записать целое число 145 687 в двоичный файл, то он будет иметь размер четыре байта, так как именно столько необходимо для хранения данных типа int. То есть двоичные файлы более компактны и в некоторых случаях более удобны для обработки. Для того чтобы открыть двоичный файл, необходимо задать режим доступа ios::binary (в некоторых компиляторах C++ - ios::bin). Для создания выходного файла создают объект: ofstream outBinFile("out.bin", ios::out | ios::binary); /* создание объекта класса
ofstream out. bin if (! out_f і 1) //стандартная проверка
Запись данных происходит с помощью метода write (), который имеет два параметра: первый - указатель на начало (адрес начала) записываемых данных, второй - количество записываемых байтов. При этом указатель необходимо явно преобразовать к типу char. Пример 1.
Записать в двоичный файл переменные различного типа: ofstream outBinFile("test.bin", ios::out I ios: :binary) ; /^создание объекта класса
of stream и попытка связать его с файлом
test. bin в режиме записи двоичного файла */
int а - 145687; //объявление целой переменной
а outBinFi le. write ((char*) &а, sizeof (а)) ; /^запись в файл
переменной
а как потока байтов, т. е. запись в файл внутреннего представления целой переменной
а */ float х - 123.25; // объявление вещественной переменной
х outBinFile .write ((char*) &х, sizeof (х)) ; /^запись в файл
переменной
х как потока байтов, т. е. запись в файл внутреннего представления целой переменной х*/
//определение символьной переменной
с и инициализация ее символом g
outBinFile.write((char*)&c, sizeof(c)); //запись символа
g в файл
outBinFile.close(); return 0; Если открыть содержимое файла test .bin текстовым редактором, то он будет иметь вид: а размер файла составит 9 байт. Для того чтобы открыть существующий двоичный файл для чтения, нужно создать объект: ifstream inpBinFile("inp.bin", ios::in I ios::binary); /* используем дизъюнкцию флагов, указывающую на то что файл открывается на чтение в двоичном виде*/
if (! inpBinFile) coutДля чтения данных используем функцию read(), имеющую аналогичные функции write() параметры. #include using namespace std; int main() ifstream inpBinFile("test.bin", ios::in I ios: : binary) ; //открываем файл на чтение в двоичном виде
int а; float х; char с = "g"; inpBinFile.read((char*)&a, sizeof(a)); //читаем целочисленную переменную
inpBinFile.read((char*)&x, sizeof(x)); //читаем вещественную переменную
inpBinFile.read((char*)&c, sizeof (c)); //читаем символьную переменную
inpBinFile.close(); cout Результат работы программы: а = 145687 х = 123.25 с = g Обратите внимание, что при использовании функции write и read не происходит никакого преобразования информации. В файл записывается и считывается внутреннее представление данных. Именно поэтому две предыдущие программы дали правильный результат. В отличие от текстовых файлов, работа с пользовательскими типами данных с использованием двоичных файлов ничем не отличается от стандартных типов данных. Аналогично используются методы write() и read(). Программисту только остается указать адрес записываемого участка памяти и количество записываемых байтов, учтя при этом, что никакого преобразования данных не происходит, записывается и считывается только внутреннее представление информации. Также при работе с двоичными файлами могут использоваться методы seekg(), tellg(), seekp(), tellp(). Пример 3.
Написать программу, которая записывает сведения о группе туристов в двоичный файл. fstream BinFile("ankety.bin", ios::in I ios::out | ios::binary); Anketa Gruppa = ; for (int i = 0; i BinFile.write((char*)&Gruppa[i], sizeof(Anketa)); BinFile.close(); return 0; Пример 4.
В файле «ankety.bin» содержатся данные о группе туристов, необходимо считать их и вывести на экран. #include using namespace std; struct Anketa { char name; int age;
структурного типа данных
Anketa на экран*/
ostream& operator fstream BinFile("ankety.bin", ios::in | ios::out | ios::binary); if (!BinFile) for (int i = 0; i //сразу читаем все байты, занимаемые переменной типа
Anketa BinFile.read((char*)&Gruppa[i], sizeof(Anketa)); BinFile.close(); return 0; Результат работы программы: Ivanov, 23 Sidorov, 21 Petrov,22 Для продолжения нажмите любую клавишу. . . Постоянно пользоваться методами write() и read() неудобно, гораздо приятнее иметь возможность пользоваться операциями «>» по аналогии с текстовыми файлами. Приведем пример реализации своего класса для работы с двоичными файлами. using namespace std; struct Anketa //объявляем структуру для хранения информации
/*перегрузка операции вставки в поток для вывода пользовательского
структурного типа данных
Anketa на экран*/
ostream& operator class outBinaryFile: public of stream /^определяем свой класс для работы с выходными бинарными файлами. Порождаем его от класса работы с выходными файловыми потоками*/
/*при описании конструктора порожденного класса не забываем вызвать конструктор базового, передав ему необходимые параметры*/
outBinaryFile(char* name) : ofstream(name, ios::out I ios::binary) //перегружаем необходимые операции как методы класса
outBinaryFile& operator write((char*)&chislo, sizeof(chislo)); return *this; outBinaryFile& operator write((char*)&ank, sizeof(ank)); return *this; class inpBinaryFile: public if stream /* определяем свои класс для работы с входными бинарными файлами. Порождаем его от класса работы с входными файловыми потоками*/
inpBinaryFile(char* name) : ifstream(name, ios::in I ios::binary) /*вызова конструктора базового класса с необходимыми параметрами,
достаточно для конструктора порожденного класса */
//перегружаем необходимые операции
inpBinaryFile& operator >> (int& chislo) read((char*)&chislo, sizeof(chislo)); return *this; inpBinaryFile& operator >> (Anketa& ank) read((char*)&ank, sizeof(ank)); return *this; int а = 111, b = 112; outBinaryFile outFile("dannye.bin"); //открываем файл на чтение
inpBinaryFile inpFile("dannye.bin"); if (!inpFile) for (int і = 0; i inpFile >> a; //читаем анкету из файла
cout //и выводим ее на экран inpFile >> anketa; cout Результат работы программы: Kolya, 1990, 582-78-95. Для продолжения нажмите любую клавишу. . . 1. Можно ли в программе использовать операцию? ios::in I ios::out З.Что будет выведено на экран в результате выполнения следующего кода? inputFile.get(с); next - inputFile.peek(); if (next == EOF) Контрольные вопросыОписание записи с вариантной частью
Механизм использования записи с вариантной частью
name, publisher
item
Вариантная часть
...
"b"
author
year
...
"n"
data
...
"m"
year
month
number
...
"b"
author
year
Бинарные файлы
Работа с двоичными файлами
Запись стандартных типов данных в двоичные файлы
Чтение стандартных типов данных из двоичных файлов
Запись и чтение пользовательских типов данных в двоичные файлы
Разработка собственных классов для работы с файлами