Binary I/O

Binary I/O: हम Formatted I/O का प्रयोग करके कुछ ही Numbers को Disk File में Store कर सकते हैं। लेकिन यदि हमें बहुत ज्यादा Numerical Data को Disk File में Store करना हो, तो हमें Numerical Data को File में Binary Format में Store करना चाहिए। जब Disk में Data को Binary Format में Store करना होता है, तब Numerical Data Disk File में Numerical Data Strings की तरह Store होने के बजाय, उसी प्रकार से Binary Format में Store होते हैं, जिस प्रकार से वे Numerical Data RAM में Store होते हैं। Binary Format में Integer (32767) हमेंशा दो Byte में Store होता है जबकि Disk File में Store होने के लिए इसका Text Version 5 Byte तक ले सकता है।

इसी तरह से यदि किसी Floating Point मान जैसे कि 123.54 को Character Format में Disk File में Store किया जाए, तो 6 Bytes Use होंगे जबकि Binary Format में Disk पर Store करने पर केवल चार Bytes की ही जरूरत होगी।

अगले उदाहरण में हम ये समझ रहे हैं कि किस प्रकार से एक Integers के Array को Disk File में Write किया जा सकता है और उसी Binary Format में फिर किस प्रकार से File से Data को Read किया जा सकता है।

इसमें हमने दो नए Functions write() व read() Use किए हैं, जो कि क्रमश: ofstreamifstream Class के Member Functions हैं। ये Functions Data को Bytes के रूप में देखते हैं। इन Functions को इस बात से कोई मतलब नहीं होता है, कि Data किस तरह से Formatted हैं, ये केवल Characters से पूरी तरह से भरे हुए Buffer को Disk पर व Disk से Buffer में Transfer करने का काम करते हैं।

इन दोनों Functions में Parameters के रूप में Buffer का Address व Buffer की Length प्रदान करनी होती है। Address को char प्रकार में तथा Length को Bytes (Characters) की Counting के रूप में, ना कि Buffer के Data Items की संख्‍या के रूप में Cast करना जरूरी होता है।

	// binio.cpp
	// binary input and output with integers
	#include <fstream.h>                  			// for file streams

	const int MAX = 100;                  			// number of ints

	int buff[MAX];                       			// buffer for integers
	void main()
	{
	   int j;
	   for(j=0; j<MAX; j++)                			// fill buffer with data
		  buff[j] = j;                    		// (0, 1, 2, ...)
								// create output stream
	   ofstream os("edata.dat", ios::binary);
								// write to it
	   os.write( (char*)buff, MAX*sizeof(int) );
	   os.close();                        			// must close it

	   for(j=0; j<MAX; j++)               			// erase buffer
		  buff[j] = 0;                    		// create input stream
	   ifstream is("edata.dat", ios::binary);
								// read from it
	   is.read( (char*)buff, MAX*sizeof(int) );

	   for(j=0; j<MAX; j++)               			// check data
		  if( buff[j] != j )
			 { cerr << "\nData is incorrect"; return; }
	   cout << "\nData is correct";
	}

जब हम Binary Data के साथ काम करते हैं तब हमें write() व read() Functions के दूसरे Parameter के रूप में ios::binary Argument को Use करना चाहिए। ऐसा इसलिए करना चाहिए क्योंकि Text Mode यानी DOS में ‘\n’ Character Disk पर Store होने से पहले दो Bytes में Expand होता है:

एक Byte Carriage Return के लिए व एक Byte linefeed के लिए। इसका प्रयोग करने से किसी साधारण Text Editor के लिए Formatted Text ज्यादा Readable हो जाता है, लेकिन जब इसे Binary Data में Convert किया जाता है, तब कुछ Confusion हो जाता है, क्योंकि वह हर Byte जिसकी ASCII Value 10 हो दो Bytes में Translate हो जाती है।

अभी तक हमने जितनी भी Files Open की थी उनमें से किसी को Close नहीं किया था। File को Close करने के लिए उनके Destructors Automatically Call हो जाते थे। लेकिन इस Program में हमने File को Close किया है, क्योंकि Input Stream is व Output Stream वे दोनों ही समान File EDATA.DAT से Associated हैं। यहां भी हमें पहली Stream को Close करने के बाद दूसरी Stream को Close करना चाहिए। इस काम के लिए हमने close() Member Function का प्रयोग किया है।

Object I/O

क्योंकि C++ एक Object Oriented Programming Language है, इसलिए ये जानना जरूरी हो जाता है कि Objects को Disk पर किस प्रकार से Write किया जाए और पुन: Read किया जाए। अगला उदाहरण इस Process को Clear करने के लिए बनाया गया है। person Class को हमने पिछले कई उदाहरणों में Use किया है। इस Program में ये Class हमें Disk File के लिए Object Provide कर रहा है।

Writing an Object to Disk

जब हम एक Object को File में Write करना चाहते हैं, तब हम सामान्‍यतया Binary Mode को उपयोग में लेते हैं। Binary Mode को Use करने पर Object के Data उसी प्रकार से Disk पर Write होते हैं, जिस प्रकार से वे Data Memory में Stored रहते हैं और साथ ही ये भी निश्चित हो जाता है कि Object के Numerical Data ठीक तरीके से Handle होंगे। निम्न Program User से person Class के एक Object की Information को Fill करने के लिए Messages देता है और फिर इस Object को Disk File पर Write कर देता है।

	// opers.cpp
	// saves person object to disk
	#include <fstream.h>                			// for file streams
	class person                         			// class of persons
	{
	   protected:
		  char name[40];                		// person's name
		  int age;                       		// person's age

	   public:
		void getData(void)            			// get person's data
		{
			 cout << "Enter name: "; cin >> name;
			 cout << "Enter age: "; cin >> age;
		}
	};

	void main(void)
	{
	   person pers;                       			// create a person
	   pers.getData();                    			// get data for person
								// create ofstream object
	   ofstream outfile("PERSON.DAT", ios::binary);
	   outfile.write( (char*)&pers, sizeof(pers) );  	// write to it
	}

person Class का getData() Member Function User से Information लेने के लिए Prompt करता है, जो कि pers Object में Store हो जाते हैं। Program का Interaction कुछ निम्नानुसार होता है:

Enter name: Madhav
Enter age: 62

फिर pers Object के Contents या Data Disk पर write() Function का प्रयोग करके Write कर दि, जाते हैं। pers Object की Size का पता करने के लिए हमने sizeof() Operator का प्रयोग किया है।

Reading an Object from Disk

पिछले Program द्वारा Disk File में Store किए गए Data को फिर से Read करने के लिए हम निम्न Program Use कर सकते हैं:

	// ipers.cpp
	// reads person object from disk
	#include <fstream.h>             	 // for file streams

	class person                       	// class of persons
	{
	   protected:
		  char name[40];               	// person's name
		  int age;                      // person's age

	   public:
		void showData(void)            	// display person's data
		{
			 cout << "\n   Name: " << name;
			 cout << "\n   Age: " << age;
		}
	};

	void main(void)
	{
	   person pers;                     	// create person variable
	   ifstream infile("PERSON.DAT", ios::binary); 	// create stream
	   infile.read( (char*)&pers, sizeof(pers) ); 	// read stream
	   pers.showData();                           	// display person
	}

 

Compatible Data Structures

ठीक तरह से काम करने के लिए वे Programs जो कि Files से Data को Read व Files में Data को Write करते हैं, जैसाकि पिछले दोनों Programs में opersipers ने किया है, वे दोनों समान Class के होने जरूरी होते हैं।

person Class के Objects Exactly 42 Bytes के हैं, जिसमें पहले 40 Bytes Person के नाम को Store करने के लिए हैं और बाकी के दो Bytes Person की Age को Store करने के लिए Use होते हैं। यदि इस File को Read करने के लिए किसी दूसरी Class के Object को Use किया जाता है, जो कि समान प्रकार के Bytes को Read नहीं करते हैं।

यानी नाम के लिए 40 Bytes व Age के लिए दो Bytes को Hold करने के Variables Data Member के रूप में Class में Declare नहीं किए गए हैं, तो File के Data का उचित तरीके से Read होना मुश्किल होता है।

यानी जिस Program में जिस Class के Object को Use करके Disk File में Data को Store किया गया है, यदि दूसरे Program में उसी Class के Object का प्रयोग करके Data को Read ना किया जाए तो हमें Accurate Output कभी प्राप्त नहीं हो सकता है।

ध्‍यान दें, कि हालांकि दोनों Programs के person Objects के Data समान हैं, फिर भी उनके Member Functions अलग-अलग हो सकते हैं। पहले Object में एक Single Function getData() है जबकि दूसरे Program में केवल एक showData() Member Function ही है। इस बात से कोई फर्क नहीं पडता है कि हम किस Member Function को Use करते हैं, क्योंकि Object के Data के साथ उनके Member Functions Disk पर Write नहीं होते हैं।

Data का Format समान होना जरूरी होता है जबकि Object के साथ Use होने वाले Member Functions के प्रयोग में अनुरूपता होना जरूरी नहीं होता है। ये बात केवल उन Classes के सम्बंध मे लागू होती है, जिनमें Virtual Functions का प्रयोग नहीं होता है।

यदि हम किसी File से किसी Derived Class के Object के Data को Read या Write करते हैं, तो उस स्थिति में हमें ज्यादा सावधान रहना जरूरी होता है। उन Derived Classes के Objects जिनमें Virtual Functions होते हैं, उनमें vptr होते हैं। ये एक ऐसा Table होता है, जो Class में Use होने वाले सभी Virtual Functions के Address को Hold करके रखता है। जब हम किसी Object को Disk पर Write करते हैं, तब उस Virtual Function का Address Object के अन्‍य Data के साथ Disk पर Write होता है।

यदि हम Class के Member Function को Change करते हैं, तो Object के Data के साथ Disk पर Write होने वाले Function का Address भी Change हो जाता है। यदि हम किसी Object के Data को Virtual Function का प्रयोग करके Disk पर Write करते हैं और उसी Class के किसी Object द्वारा उस File से Object के Data को Read करते हैं, लेकिन किसी अन्‍य Member Function को प्रयोग करके ऐसा करते हैं, तो हम बहुत बडी मुसीबत में फंस सकते हैं।

इसलिए हमें कभी भी किसी Virtual Function का प्रयोग करके किसी Object के Data को File में Store नहीं करना चाहिए। सारांश ये है कि हम जिस Object का प्रयोग करके किसी Disk से Object के Data को Read कर रहे हैं, वह Object Disk पर Data को Write करने वाले Object के Identical यानी समान Class का होना चाहिए।

I/O with Multiple Objects

पिछले दोनों Programs में हमने File पर केवल एक ही Object के Data को Write किया और उसे फिर से Read किया है। अगले उदाहरण में हम देख रहे हैं कि हम जितने चाहें उतने Objects को Disk File में Write कर सकते हैं और फिर से Read कर सकते हैं।

	// diskfun.cpp
	// reads and writes several objects to disk
	#include <fstream.h>                 	// for file streams

	class person                          	// class of persons
	   {
		protected:
			char name[40];          // person's name
			int age;                // person's age

		   public:
			void getData(void)      // get person's data
			{
				cout << "\n   Enter name: "; cin >> name;
				cout << "   Enter age: "; cin >> age;
			 }

			void showData(void)      // display person's data
			 {
				 cout << "\n   Name: " << name;
				 cout << "\n   Age: " << age;
			 }
	  };

	void main(void)
	{
	   	char ch;
	  	person pers;                      // create person object
	   	fstream file;                     // create input/output file
						  // open for append
	   	file.open("PERSON.DAT", ios::app | ios::out | ios::in | ios::binary );

	   	do                               // data from user to file
		{
		  cout << "\nEnter person's data:";
		  pers.getData();                // get one person's data
						// write to file
		  file.write( (char*)&pers, sizeof(pers) );
		  cout << "Enter another person (y/n)? ";
		  cin >> ch;
		}
	   	while(ch=='y');                 // quit on 'n'

	   	file.seekg(0);                  // reset to start of file
						// read first person
	   	file.read( (char*)&pers, sizeof(pers) );

	   	while( !file.eof() )           // quit on EOF
		{
		  cout << "\nPerson:";         // display person
		  pers.showData();
		  file.read( (char*)&pers, sizeof(pers) ); 	// read another
		}                              // person
	}

इस File में एक Additional Object को Add किया गया है और बाद में तीनों Objects के Data को Screen पर Print किया गया है। (Binary I/O)

Enter person's data:
   Enter name: Brijvasi
   Enter age: 22
Enter another person (y/n)? n

Person:
   Name: Mohan
   Age: 20
Person:
   Name: Madhav
   Age 21
Person:
   Name: Brijvasi
   Age: 22

CPP Programming Language in Hindiये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook C++ Programming Language in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

C++ Programming Language in Hindi | Page: 666 | Format: PDF

BUY NOW GET DEMO REVIEWS