Считывание бинарного файла c. Работа с бинарными файлами. BinaryWriter и BinaryReader
Для работы с бинарными файлами предназначена пара классов BinaryWriter и BinaryReader . Эти классы позволяют читать и записывать данные в двоичном формате.
Основные метода класса BinaryWriter
Flush() : очищает буфер, дописывая из него оставшиеся данные в файл
Seek() : устанавливает позицию в потоке
Write() : записывает данные в поток
Основные метода класса BinaryReader
Close() : закрывает поток и освобождает ресурсы
ReadBoolean() : считывает значение bool и перемещает указатель на один байт
ReadByte() : считывает один байт и перемещает указатель на один байт
ReadChar() : считывает значение char, то есть один символ, и перемещает указатель на столько байтов, сколько занимает символ в текущей кодировке
ReadDecimal() : считывает значение decimal и перемещает указатель на 16 байт
ReadDouble() : считывает значение double и перемещает указатель на 8 байт
ReadInt16() : считывает значение short и перемещает указатель на 2 байта
ReadInt32() : считывает значение int и перемещает указатель на 4 байта
ReadInt64() : считывает значение long и перемещает указатель на 8 байт
ReadSingle() : считывает значение float и перемещает указатель на 4 байта
ReadString() : считывает значение string. Каждая строка предваряется значением длины строки, которое представляет 7-битное целое число
С чтением бинарных данных все просто: соответствующий метод считывает данные определенного типа и перемещает указатель на размер этого типа в байтах, например, значение типа int занимает 4 байта, поэтому BinaryReader считает 4 байта и переместит указать на эти 4 байта.
Посмотрим на реальной задаче применение этих классов. Попробуем с их помощью записывать и считывать из файла массив структур:
Struct State { public string name; public string capital; public int area; public double people; public State(string n, string c, int a, double p) { name = n; capital = c; people = p; area = a; } } class Program { static void Main(string args) { State states = new State; states = new State("Германия", "Берлин", 357168, 80.8); states = new State("Франция", "Париж", 640679, 64.7); string path= @"C:\SomeDir\states.dat"; try { // создаем объект BinaryWriter using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.OpenOrCreate))) { // записываем в файл значение каждого поля структуры foreach (State s in states) { writer.Write(s.name); writer.Write(s.capital); writer.Write(s.area); writer.Write(s.people); } } // создаем объект BinaryReader using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open))) { // пока не достигнут конец файла // считываем каждое значение из файла while (reader.PeekChar() > -1) { string name = reader.ReadString(); string capital = reader.ReadString(); int area = reader.ReadInt32(); double population = reader.ReadDouble(); Console.WriteLine("Страна: {0} столица: {1} площадь {2} кв. км численность населения: {3} млн. чел.", name, capital, area, population); } } } catch (Exception e) { Console.WriteLine(e.Message); } Console.ReadLine(); } }
Итак, у нас есть структура State с некоторым набором полей. В основной программе создаем массив структур и записываем с помощью BinaryWriter. Этот класс в качестве параметра в конструкторе принимает объект Stream, который создается вызовом File.Open(path, FileMode.OpenOrCreate) .
Затем в цикле пробегаемся по массиву структур и записываем каждое поле структуры в поток. В том порядке, в каком эти значения полей записываются, в том порядке они и будут размещаться в файле.
Затем считываем из записанного файла. Конструктор класса BinaryReader также в качестве параметра принимает объект потока, только в данном случае устанавливаем в качестве режима FileMode.Open: new BinaryReader(File.Open(path, FileMode.Open))
В цикле while считываем данные. Чтобы узнать окончание потока, вызываем метод PeekChar() . Этот метод считывает следующий символ и возвращает его числовое представление. Если символ отсутствует, то метод возвращает -1, что будет означать, что мы достигли конца файла.
В цикле последовательно считываем значения поле структур в том же порядке, в каком они записывались.
Таким образом, классы BinaryWriter и BinaryReader очень удобны для работы с бинарными файлами, особенно когда нам известна структура этих файлов. В то же время для хранения и считывания более комплексных объектов, например, объектов классов, лучше подходит другое решение - сериализация.
ДВОИЧНАЯ ЗАПИСЬ
(binary notation) Запись чисел только двумя символами. Символами, как правило, являются 0 и 1, которые называются двоичными разрядами (binary digits), или битами (bits). Биты обычно группируются по восемь символов, называемых байтами (bytes). Числа, записанные в двоичной форме, выглядят значительно длиннее, чем при десятичной записи. Например, двоичное число 1111 является эквивалентом записанного в десятичной форме числа 15. В двоичном числе колонки справа налево представляют собой "единицы", "двойки", "четверки", "восьмерки" и т.д. Двоичная используется в компьютерных расчетах по той причине, что цифровые компьютеры представляют числа в форме наличия (1) или отсутствия (0) электрического импульса.
Бизнес. Толковый словарь. - М.: "ИНФРА-М", Издательство "Весь Мир". Грэхэм Бетс, Барри Брайндли, С. Уильямс и др. Общая редакция: д.э.н. Осадчая И.М. . 1998 .
Смотреть что такое "ДВОИЧНАЯ ЗАПИСЬ" в других словарях:
двоичная запись - — [Л.Г.Суменко. Англо русский словарь по информационным технологиям. М.: ГП ЦНИИС, 2003.] Тематики информационные технологии в целом EN binary notation … Справочник технического переводчика
Система счисления (См. Счисление), построенная на позиционном принципе записи чисел, с основанием 2. В Д. с. с. используются только два знака цифры 0 и 1; при этом, как и во всякой позиционной системе, значение цифры зависит дополнительно … Большая советская энциклопедия
Эта статья или раздел нуждается в переработке. Пожалуйста, улучшите статью в соответствии с правилами написания статей … Википедия
- (decimal notation) Повседневная система записи чисел цифрами от 0 до 9. В десятичном числе место цифры, считая справа налево, показывает увеличение кратности числа 10. См. также: двоичная запись (binary notation). Бизнес. Толковый словарь. М.:… … Словарь бизнес-терминов
- (RSA Signature Scheme with Appendix Probabilistic Signature Scheme) асимметричный алгоритм цифровой подписи. Основан на принципе кодирования PSS, предложенном в 1996 году авторами Mihir Bellare и Phillip Rogaway. Внесён в стандарт PKCS#1 v2.1… … Википедия
- (bit) Аббревиатура понятия двоичный разряд. См.: двоичная запись (binary notation). Бизнес. Толковый словарь. М.: ИНФРА М, Издательство Весь Мир. Грэхэм Бетс, Барри Брайндли, С. Уильямс и др. Общая редакция: д.э.н. Осадчая И.М.. 1998. Бит … Словарь бизнес-терминов
Калифорнийский автомобильный номер на Leet: T3h1337 (Teh Leet) Leet (1337) распространившийся в Интернете стиль употребления английского языка. Основные отличия замена латинских букв на похожие цифры и символы, имитация и … Википедия
У этого термина существуют и другие значения, см. Nimrod (значения). Nimrod Nimrod (также NIMROD) компьютер для игры в ним. Имел режимы как для игры человека с компьютером, так и для игры компьютера с … Википедия
- имеет имя на диске, что дает возможность программам идентифицировать и работать с несколькими файлами;
- длина файла ограничивается только емкостью диска.
Часто бывает необходимо ввести некоторые данные из файла или вывести результаты в файл . Например, бывает необходимо обрабатывать массивы, которые слишком велики, чтобы полностью разместиться в памяти.
Файлы делятся на текстовые и двоичные.
Текстовый файл – это файл , в котором каждый символ из используемого набора символов хранится в виде одного байта (кода, соответствующего символу). Текстовые файлы разбиваются на несколько строк с помощью специального символа "конец строки". Текстовый файл заканчивается специальным символом " конец файла ".
Двоичный файл – файл , данные которого представлены в бинарном виде. При записи в двоичный файл символы и числа записываются в виде последовательности байт (в своем внутреннем двоичном представлении в памяти компьютера).
Особенностью языка С++ является отсутствие в нем структурированных файлов. Все файлы рассматриваются как неструктурированная последовательность байтов. При таком подходе понятие файла распространяется и на различные устройства.
В С++ существуют специальные средства ввода-вывода данных. Все операции ввода-вывода реализуются с помощью функций, которые находятся в библиотеке С++. Библиотека С++ поддерживает три уровня ввода-вывода:
- потоковый ввод-вывод;
- ввод-вывод нижнего уровня;
- ввод-вывод для консоли и портов (зависит от ОС).
Поток – это абстрактное понятие, относящееся к любому переносу данных от источника к приемнику.
Функции библиотеки ввода-вывода языка С++, поддерживающие обмен данными с файлами на уровне потока, позволяют обрабатывать данные различных размеров и форматов, обеспечивая при этом буферизованный ввод и вывод . Таким образом, поток представляет собой этот файл вместе с предоставленными средствами буферизации.
Чтение данных из потока называется извлечением, вывод в поток – помещением (включением) .
Поток определяется как последовательность байтов и не зависит от конкретного устройства, с которым производится обмен ( оперативная память , файл на диске, клавиатура или принтер). Обмен с потоком для увеличения скорости передачи данных производится, как правило, через специальную область оперативной памяти – буфер . Буфер накапливает байты, и фактическая передача данных выполняется после заполнения буфера ( рис. 19.1). При вводе это дает возможность исправить ошибки, если данные из буфера еще не отправлены в программу.
Рис.
19.1.
При работе с потоком можно:
- открывать и закрывать потоки (связывать указатели на поток с конкретными файлами);
- вводить и выводить строку, символ, форматированные данные, порцию данных произвольной длины;
- анализировать ошибки ввода-вывода и достижения конца файла;
- управлять буферизацией потока и размером буфера;
- получать и устанавливать указатель текущей позиции в файле.
Когда программа начинает выполняться, автоматически открываются пять потоков, из которых основными являются:
- стандартный поток ввода (на него ссылаются, используя предопределенный указатель на поток stdin );
- стандартный поток вывода (stdout );
- стандартный поток вывода сообщений об ошибках (stderr ).
По умолчанию стандартному потоку ввода stdin ставится в соответствие клавиатура, а потокам stdout и stderr соответствует экран монитора.
В С++ операции с файлами можно осуществлять в двух режимах: форматированном и потоковом .
Рассмотрим основные функции для работы с файлами в форматированном режиме.
Функция открытия файла
Для работы с файлом в языке C++ необходима ссылка на файл . Для определения такой ссылки существует структура FILE , описанная в файле stdio.h . Данная структура содержит все необходимые поля для управления файлами, например: текущий указатель буфера, текущий счетчик байтов, базовый адрес буфера ввода-вывода, номер файла.
При открытии файла (потока) в программу возвращается указатель на поток (файловый указатель ), являющийся указателем на объект структурного типа FILE . Этот указатель идентифицирует поток во всех последующих операциях.
Например:
#include
Для открытия файла существует функция fopen , которая инициализирует файл .
Синтаксис :
fp=fopen(ИмяФайла, РежимОткрытия);
где fp – указатель на поток (файловый указатель );
ИмяФайла – указатель на строку символов, представляющую собой допустимое имя файла , в которое может входить спецификация файла (включает обозначение логического устройства, путь к файлу и собственно имя файла );
РежимОткрытия – указатель на строку режима открытия файла.
Например:
fp=fopen("t.txt","r");
Существуют несколько режимов открытия файлов.
Режим | Описание | Начинается с... |
---|---|---|
r | Открывает текстовый файл для чтения. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
w | Открывает текстовый файл для записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается | начала |
a | Открывает текстовый файл для добавления. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
r+ | Открывает текстовый файл для чтения и записи. Изменить размер файла нельзя. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
w+ | Открывает текстовый файл для чтения и записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается. | начала |
a+ | Открывает текстовый файл для чтения и записи. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
rb | Открывает двоичный файл для чтения. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
wb | Открывает двоичный файл для записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается. | начала |
ab | Открывает двоичный файл для добавления. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
r+b | Открывает двоичный файл для чтения и записи. Изменить размер файла нельзя. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
rb+ | ||
w+b | Открывает двоичный файл для чтения и записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается. | начала |
wb+ | ||
a+b | Открывает двоичный файл для чтения и записи. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
ab+ |