Ввод-вывод двоичных данных


Для ввода-вывода двоичных данных используются функции (методы классов ostream и istream) put, write и get, которые определены следующим образом:

ostream& ostream::put(char ch);//посылает ch в ostreamostream& ostream::write(const char* buff, int n);//посылает n символов из buff в ostream;

Put и write позволяют выводить неформатированные двоичные данные в объект ostream. Put выводит один символ, а write может послать любое количество символов из указанного буфера. Write полезна, когда нужно вывести необработанные данные, которые могут включать нули. (Запись двоичных данных требует, чтобы файл был открыт в двоичном режиме.)

Обычное извлечение строки не будет работать до тех пор, пока строка не будет завершена нулем.

Входная версия put называется get:

char ch;cin.get(ch); //захватывает следующий символ из //cin независимо от того пробел это или нет

Другая версия get позволяет захватывать любое количество необработанных, двоичных символов из istream до заданного максимума и помещать их в заданный буфер (так же, как и в случае с write, файлы должны быть открыты в двоичном режиме):

istream& istream::get(char *buff, int max, int term='\n');//читает символы до максимального количества из istream, а//затем помещает их в buff. Прекращает чтение, если//прочитан//символ, указанный в term.

Можно установить term равным определенному конечному символу (по умолчанию — это символ новой строки), в котором get будет прекращать работу, если он будет достигнут прежде, чем max символов будет передано в buff.

Ввод/вывод с диска

Библиотека iostream включает много классов, порожденных из streambuf, ostream и istream, предоставляя, таким образом, широкий выбор методов ввода/вывода файлов. Класс filebuf например, поддерживает ввод/вывод через дескрипторы файлов с помощью функций элементов для открытия, закрытия и поиска.

Наиболее часто используемыми классами являются ifstream (порожденный из istream), ofstream (порожденный из ostream) и fstream (порожденный из iostream). Все они поддерживают форматированный файл ввода/вывода, используя объекты filebuf. Ниже приведен простой пример, который копирует существующий дисковый файл в другой заданный файл:

/* DCOPY исходный файл / файл назначения ** копирует существующий исходный файл в файл назначения ** Если последний существует, то он перезаписывается; ** если не существует, DCOPY создаст его, если это возможно **/#include <iostream.h>#include <process.h> // для exit()#include <fstream.h> // для ifstream, ofstreamint main(int argc, char* argv[]) { char ch; if (argc != 3) // проверка числа аргументов { cerr << "USAGE: dcopy file1 file2\n"; exit(-1); } ifstream source; // объявить входной и выходной потоки ofstream dest; source.open(argv[1],ios::nocreate); // должен быть исходный файл if (!source) { cerr << "Cannot open source file " << argv[1] << " for input\n"; exit(-1); } dest.open(argv[2]); // файл назначения будет создан, если // не он найден или создан/перезаписан, если найден if (!dest) { cerr << "Cannot open destination file " << argv[2] << " for output\n"; exit(-1); } while (dest && source.get(ch)) dest.put(ch); cout << "DCOPY completed\n"; source.close(); // закрыть оба потока dest.close();}

Типичный вызов этой программы в командной строке выглядит следующим образом:

dcopy letter.spr letter.bak

Пример 2. Разработать программу для ввода/вывода с диска массива структур.

#include <iostream.h>#include <fstream.h> int main(int argc, char* argv[]){ struct emp { char* name; int dept; }; emp e[2]; e[0].name="aaaa"; e[0].dept=1; e[1].name="bbbbbbb"; e[1].dept=2; ifstream source; ofstream dest; char filename[20]="s.dat"; dest.open(filename); for(int i=0;i<2;i++) dest<<e[i].name<<" "<<e[i].dept<<endl; dest.close(); source.open(filename,ios::nocreate); // файл должен быть создан for(int i=0;i<2;i++) { source>>e[i].name>>e[i].dept; cout<<e[i].name<<" "<<e[i].dept<<endl; } source.close(); cin.get(); return 0;}

При этом файл s.dat содержит следующие данные:

aaaa 1bbbbbbb 2

Если поле name может содержать пробелы, то такой способ ввода/вывода непригоден. Нужно использовать разделитель полей, отличный от пробела, например, @.

for(int i=0;i<2;i++) dest<<e[i].name<<"@"<<e[i].dept<<endl;

Теперь чтение данных будет выглядеть следующим образом:

char buf[22];for(int i=0;i<2;i++){ source.get(e[i].name, 100, '@'); source.get(); //отбросить @ source.get(buf, 100, '\n'); source.get(); //отбросить \n e[i].dept=atoi(buf); cout<<e[i].name<<" "<<e[i].dept<<endl;}


Дата добавления: 2016-07-27; просмотров: 1559;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.008 сек.