Disk File I/O with Streams: Keyboard व Screen Files के साथ Use की जा रही Classes की तुलना में जब हम Disk File पर काम करते हैं, तब हमें अलग प्रकार की Classes की जरूरत पडती है। इसके लिए भी तीन Classes हैं:
ifstream For Input
ofstream For Output
fstream For Both Input and Output
इस Class के Objects को Disk Files के साथ Associate किया जा सकता है और हम इनके Member Functions को Files की Reading व Writing के लिए Use कर सकते हैं। ifstream को istream से Derive किया गया है, fstream को iostream से Derive किया गया है और ofstream को ostream से Derive किया गया है। जबकि इन ऊपर की Classes को ios Class से Derive किया गया है।
अतरू इन File Oriented Classes में कई General Classes के कई Member Functions Inherit होते हैं। File Oriented Classes को Multiple Inheritance द्वारा fstreambase Class से Derive किया गया है।
इस Class में filebuf Class का एक Object होता है, जो कि एक File Oriented Buffer होता है और इस File Oriented Buffer से Associated Member Functions कई और General streambuf Classes से Inherited होती हैं। कई File-Based Operations के लिए streambuf Automatically Accessed हो जाता है लेकिन हम ऐसी स्थिति भी देखेंगे, जहां हम इसे समान रूप से Directly Access कर सकेंगे।
ifstream, ofstream व fstream Classes को FSTREAM.H नाम की Header File में Declare किया गया है। इस File में IOSTREAM.H Header File को भी Include किया गया है। इसलिए इस File को अलग से Include करने की जरूरत नहीं रहती है। FSTREAM.H File ही सभी प्रकार के stream I/O को Handle करने के लिए सभी जरूरी Classes प्रदान कर देती है।
जिन्होंने पहले C Language में Disk I/O से सम्बंधित Programming की है, वे देखेंगे कि C व C++ की Disk I/O की तकनीक में काफी अन्तर है। C Language के सभी Functions C++ में भी समान रूप से काम करते हैं लेकिन Object Oriented Programming के कारण इन्हें ठीक तरीके से Use नहीं किया जा सकता है। printf() व scanf() Functions को हम हमारे तरीके से Use नहीं कर सकते हैं, जबकि C++ Iostream Class के Operators को हम हमारे तरीके से Overload करके या Modify करके Use कर सकते हैं। (Disk File I/O with Streams – CProgramming)
Formatted File I/O
C++ में Formatted व Binary दो प्रकार के Disk I/O होते हैं। Formatted I/O में Disk पर Numbers Characters की एक Series के रूप में Store होते हैं। यानी यदि 8.12 को Disk पर Store किया जाए, तो ये Number Memory में चार Byte लेगा लेकिन ये Float के या Double के रूप में Disk पर Store नहीं होगा बल्कि एक String के रूप में Store होगा। हालांकि ये Efficient तरीका नहीं है, लेकिन कई स्थानों पर ये एक उचित तरीका होता है और इससे Implement करना सरल होता है।
Writing Data
निम्न Program एक Character, एक Integer, एक Float, एक Double व दो Strings को Disk पर Store करता है और इस Disk File का नाम FDATA.TXT रखा गया है। इस Program को Run करने पर Output में कुछ भी दिखाई नहीं देगा।
// formato.cpp // writes formatted output to a file, using << #include <fstream.h> // for file I/O #include <conio.h> void main() { char ch = 'x'; // character int j = 77; // integer double d = 154545.6565; // floating point char str1[] = " ManMohan "; // strings char str2[] = "Brijwasi"; // (no embedded spaces) ofstream outfile("fdata.txt"); // create ofstream object outfile << ch // insert (write) data << j << ' ' // needs space between numbers << d << str1 << ' ' // needs space between strings << str2; cout << "File Created on the location of the program "; } // Output in the File FDATA.TXT x77 154546 ManMohan Brijwasi
इस Program में हमने outfile नाम का एक ofstream Class का Object Create किया है। Object Create करते समय ही ये Program उस Create होने वाले Object यानी Disk File का नाम FDATA.TXT Initialize करता है। ये Initialization File के लिए विभिन्न प्रकार के Resources उपलब्ध करवाता है और इस नाम की File को Disk पर Open या Access करता है। यदि File Disk पर उपलब्ध नहीं होती है तो इस नाम की File Disk पर Create होती है। यदि File Disk पर होती है, तो वह File Truncate हो जाती है और नए Data पुराने Data को Replace कर देते हैं।
यानी नए Data पुराने Data पर Overwrite हो जाते हैं। outfile Object लगभग उसी प्रकार से काम करता है, जिस तरह से cout Object करता है, इसीलिए Insertion Operator << का प्रयोग करके Basic प्रकार के Variables के मानों को Disk पर यानी Disk File में भेजा गया है।
ऐसा किया जा सकता है क्योंकि Insertion Operator को ostream Class में Appropriate तरीके से Overload किया गया है, जिससे ofstream Classes Derived है। जब Program Terminate होता है तब outfile Object Out of Scope हो जाता है। अत: outfile का Destructor Call होता है, जो कि File को Close कर देता है। यानी हमें Open की गई File को अलग से Close करने की जरूरत नहीं होती है।
इस File में Formatting से सम्बंधित कई कमियां हैं। सबसे पहली कमी तो ये है कि हमें विभिन्न प्रकार के Numbers को Blank Space Character का प्रयोग करके अलग-अलग करना पडता है। क्योंकि सभी Numbers Characters की एक श्रृंखला के रूप में Disk पर Store होते हैं, ना कि एक Fixed Length Field के रूप में, इसलिए जब Disk पर Store किए गए Number को फिर से Read करना होता है, तब ये Blank Space ही वह आधार होता है, जिसका Extraction Operator प्रयोग करके पता लगाता है कि पहला Number कहां समाप्त हो रहा है और दूसरा Number कहां से शुरू हो रहा है।
इसी कारण से हमने इस Program में विभिन्न Whitespaces को outfile में Store किया है। इसी Whitespace Delimiter का प्रयोग हमने Numbers को Numbers से व String को String से अलग करने के लिए किया है। Characters को अलग करने के लिए इस Delimiter की जरूरत नहीं होती है क्योंकि उनकी एक निश्चित Length होती है।
Reading Data
निम्न Program में जो File Create की जा रही है उसे ifstream Object को Use करके बनाया गया कोई भी Program, जिसमें इसके द्वारा Create होने वाली File का नाम Initialize किया जाता है, को Read कर सकता है। जब Object Create किया जाता है, तब सम्बंधित File Automatically Open हो जाती है। फिर Program Extraction Operator >> का प्रयोग करके File को Read कर सकता है। निम्न Program FDATA.TXT File के Data को फिर से Read कर सकता है:
// formatting.cpp // reads formatted output from a file, using >> #include <fstream.h> const int MAX = 80; void main() { char ch; // empty variables int j; double d; char str1[MAX]; char str2[MAX]; ifstream infile("fdata.txt"); // create ifstream object // extract (read) data from it infile >> ch >> j >> d >> str1 >> str2; cout << ch << endl // display the data << j << endl << d << endl << str1 << endl << str2 << endl; }
इस Program में ifstream Object जिसका नाम हमने infile दिया है, एक cin Object की तरह काम करता है। चूंकि हमने जब File Create की थी तब Data को सही Format में Save किया था। इसलिए Disk से Data को उसी Format में प्राप्त करके विभिन्न प्रकार के Variables में Store करने और उनके Contents को Output में Display करने में हमें कोई परेशानी नहीं होती है। इस Program का Output हमें निम्नानुसार दिखाई देता है:
// Output x 77 154545.6565 ManMohan Brijwasi
Output में हम देख सकते हैं कि Numbers वापस से उनके Binary Representation में Convert होने के बाद Display हो रहे हैं। यानी मान 77 दो Character नहीं बल्कि एक Integer है। इसी तरह से 154545.6565 Characters का एक समूह नहीं बल्कि एक Double प्रकार का मान है।
Strings with Embedded Blanks
जो तकनीक हमने पिछले Program में Use की है, वह तब काम नहीं करती है जब हम इस प्रकार की Strings के साथ काम करते हैं, जिसमें Blank Spaces का प्रयोग होता है। इस प्रकार की Strings को Handle करने के लिए हमें हर String के बाद एक Specific Delimiter Character की जरूरत होती है और इन Strings को Disk से Read करने के लिए हमें Extraction Operator के स्थान पर getline() Function को Use करना पडता है। निम्न Program कुछ Strings को Output में Display करता है, जिन्हें Blank Spaces से अलग किया गया है:
// StringWithSpace.cpp // file output with strings #include <fstream.h> // for file functions void main() { ofstream outfile("TEST.TXT"); // create file for output // send text to file outfile << "I fear thee, ancient Mariner!\n"; outfile << "I fear thy skinny hand\n"; outfile << "And thou art long, and lank, and brown,\n"; outfile << "As is the ribbed sea sand.\n"; }
जब हम इस File को Run करते हैं तब एक File में निम्नानुसार Data Disk पर Write हो जाते हैं, जहां हर Line एक अलग Line में Write होती है।
// Output I fear thee, ancient Mariner! I fear thy skinny hand And thou art long, and lank, and brown, As is the ribbed sea sand.
File से Strings को Extract करने के लिए Program एक ifstream Create करता है और उससे एक बार में एक Line की String को getline() Function का प्रयोग करते हुए Read करता है, जो कि istream Class का एक Member Function है। ये Function Whitespaces के साथ Characters को तब तक Read करता है जब तक कि उसे \’n’ New Line Character प्राप्त नहीं हो जाता है।
जैसे ही इस Function को ये Character प्राप्त होता है, getline() Function Read की गई Line को उस Buffer में भेजा जाता है, जिसे Argument के रूप में इस Function में Pass किया जाता है। Buffer की अधिकतम Size इस Function के दूसरे Argument के रूप में प्रदान की जाती है। अन्त में हर Line के बाद में Buffer के Contents को Screen पर Print कर दिया जाता है। इस काम के लिए हम निम्न Program Use करते हैं:
// iline.cpp // file input with strings #include <fstream.h> // for file functions void main() { const int MAX = 80; // size of buffer char buffer[MAX]; // character buffer ifstream infile("TEST.TXT"); // create file for input while( infile ) // until end-of-file { infile.getline(buffer, MAX); // read a line of text cout << buffer; // display it } }
इस Program का Output बिल्कुल वैसा ही प्राप्त होता है जैसा File के अन्दर Data Store होता है। Program में कुल कितनी Strings हैं, ये जानने का कोई तरीका नहीं होता है, इसलिए Program तब तक चलता रहता है, जब तक उसे EOF प्राप्त नहीं हो जाता। इस Program को उस File के Data Read करने के लिए Use नहीं करना चाहिए, जिनमें Line का अन्त Newline Character से नहीं होता है। यदि ऐसा किया जाएगा तो Program Hang हो सकता है।
Detecting End-of-File
हमने देखा है कि ios Class से Derive किए गए Objects में Error-Status Bits होते हैं जिनका प्रयोग Operations के Results को Determine करने के लिए किया जा सकता है। जब हम किसी File को थोडा&थोडा Read करते हैं, जैसाकि हमने पिछले Program में किया है, तो हमें File में किसी स्थान पर EOF Condition प्राप्त होती है। EOF Program द्वारा Hardware को दिया जाने वाला एक Signal होता है, जो Hardware को बताता है कि Read करने के लिए उस File में और Data नहीं हैं।
यानी जहां EOF प्राप्त होता है, Computer समझ जाता है, कि File का End हो चुका है और वह Control को Return कर देता है। इस स्थिति में हम File के अन्त तक पहुंचने के लिए निम्न Statement का भी प्रयोग कर सकते हैं:
while( !infile.eof() ) // Until EOF encountered
हालांकि eofbit को Check करने का मतलब ये नहीं है कि हम अन्य Error Bits जैसे कि failbit व badbit को Check नहीं करेंगे। जबकि ये Bits भी Set हो सकते हैं, चाहे तुलना में कम बार ही Set क्यों ना हों। इस स्थिति में हम Loop को निम्नानुसार Use कर सकते हैं:
while( infile.good()) //Until any error encountered
लेकिन इससे भी सरल रूप में यदि हम देखें तो हम Stream को Directly Check करवा सकते हैं। जैसाकि हमने पिछले Program में किया है। यानी:
while( infile ) // Until any error encountered
किसी भी Stream Object जैसे कि infile आदि की एक Value होती है, जिसे Usual Error Conditions व EOF को Check करने के लिए Test किया जा सकता है। यदि इनमें से कोई भी Condition True होती है, तो File Object Zero Return करता है। यदि सबकुछ ठीक तरीके से हो तो Object एक Nonzero मान Return करता है। ये मान वास्तव में एक Pointer होता है लेकिन जो “Address” Return होता है, उसका कोई विशेष Meaning नहीं होता है। इसलिए हम इसे किसी Zero या Nonzero मान के लिए ही Check करवाते हैं।
Character I/O
put() व get() Functions जो कि क्रमशरू ostream व istream Class के Members होते हैं, इन्हें Output व Input Single Character की तरह Use किया जा सकता है। इसे समझने के लिए निम्न Program देखते हैं:
// ochar.cpp // file output with characters #include <fstream.h> // for file functions #include <string.h> // for strlen() void main() { char str[] = "Love is GOD and GOD is Happiness"; ofstream outfile("TEST.TXT"); // create file for output for(int j=0; j<strlen(str); j++) // for each character, outfile.put(str[j]); // write it to file }
इस Program में एक ofstream Object Create किया जाता है। String की Length को strlen() Function का प्रयोग करके प्राप्त किया जाता है और Characters को put() Function का प्रयोग करके एक For Loop द्वारा Output में भेजा जाता है। फिर अगले Program द्वारा इस File के Data को फिर से Read किया जा सकता है।
#include <fstream.h> // for file functions void main() { char ch; // character to read ifstream infile("TEST.TXT"); // create file for input while( infile ) // read until EOF { infile.get(ch); // read character cout << ch; // display it } }
ये Program get() Function का प्रयोग करता है और File की Reading तब तक करता है जब तक कि EOF प्राप्त नहीं हो जाता। File से Read होने वाला हर Character cout Object द्वारा Screen पर Display कर दिया जाता है।
Direct Access to the streambuf Object
किसी File से Characters Read करने का अगला तरीका rdbuf() Function है जो कि ios Class का एक Member Function है। ये Function streambuf या filebuf Object का एक Pointer Return करता है जो कि Stream Object से Associated होता है। इस Object में एक Buffer होता है जो कि Stream से Read किए गए Characters को Hold करके रखता है। इसलिए हम इसके साथ Pointer को Data Object की तरह Use कर सकते हैं।
// ichar2.cpp // file input with characters #include <fstream.h> // for file functions void main() { ifstream infile("TEST.TXT"); // create file for input cout << infile.rdbuf(); // send its buffer to cout }
ये Article इस वेबसाईट पर Selling हेतु उपलब्ध EBook C++ Programming Language in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी।
C++ Programming Language in Hindi | Page: 666 | Format: PDF