1. डेटा प्रवाह

क्वचितच एखादा कार्यक्रम स्वतःसाठी बेट म्हणून अस्तित्वात असतो. कार्यक्रम सहसा "बाहेरील जगाशी" संवाद साधतात. हे कीबोर्डवरील डेटा वाचणे, संदेश पाठवणे, इंटरनेटवरून पृष्ठे डाउनलोड करणे किंवा याउलट, रिमोट सर्व्हरवर फाइल अपलोड करणे याद्वारे होऊ शकते.

आम्ही या सर्व वर्तनांचा एका शब्दात संदर्भ घेऊ शकतो: प्रोग्राम आणि बाह्य जगामध्ये डेटा एक्सचेंज . थांबा, हा फक्त एक शब्द नाही.

अर्थात, डेटा एक्सचेंज स्वतः दोन भागांमध्ये विभागले जाऊ शकते: डेटा प्राप्त करणे आणि डेटा पाठवणे. उदाहरणार्थ, तुम्ही ऑब्जेक्ट वापरून कीबोर्डवरील डेटा वाचता Scanner— हे डेटा प्राप्त करत आहे. आणि तुम्ही कमांड वापरून स्क्रीनवर डेटा प्रदर्शित करता System.out.println()— हे डेटा पाठवत आहे.

प्रोग्रामिंगमध्ये, "स्ट्रीम" हा शब्द डेटा एक्सचेंजचे वर्णन करण्यासाठी वापरला जातो. ही संज्ञा कुठून आली?

वास्तविक जीवनात, आपल्याकडे पाण्याचा प्रवाह किंवा चेतनेचा प्रवाह असू शकतो. प्रोग्रामिंगमध्ये, आमच्याकडे डेटा प्रवाह आहेत .

प्रवाह हे एक बहुमुखी साधन आहे. ते प्रोग्रामला कुठूनही (इनपुट प्रवाह) डेटा प्राप्त करण्यास आणि कोठेही डेटा पाठविण्याची परवानगी देतात (आउटपुट प्रवाह). अशा प्रकारे, दोन प्रकार आहेत:

  • एक इनपुट प्रवाह डेटा प्राप्त करण्यासाठी आहे
  • डेटा पाठवण्यासाठी आउटपुट प्रवाह आहे

प्रवाहांना 'मूर्त' बनवण्यासाठी, Java च्या निर्मात्यांनी दोन वर्ग लिहिले: InputStreamआणि OutputStream.

वर्गामध्ये InputStreamएक read()पद्धत आहे जी तुम्हाला त्यातून डेटा वाचू देते. आणि OutputStreamक्लासमध्ये एक write()पद्धत आहे जी तुम्हाला त्यावर डेटा लिहू देते. त्यांच्याकडे इतर पद्धती देखील आहेत, परंतु नंतर त्याबद्दल अधिक.

बाइट प्रवाह

आम्ही कोणत्या प्रकारच्या डेटाबद्दल बोलत आहोत? ते कोणते स्वरूप घेते? दुसऱ्या शब्दांत, हे वर्ग कोणत्या डेटा प्रकारांना समर्थन देतात?

हे जेनेरिक वर्ग आहेत, म्हणून ते सर्वात सामान्य डेटा प्रकारास समर्थन देतात - byte. एक OutputStreamबाइट्स (आणि बाइट अॅरे) लिहू शकतो आणि InputStreamऑब्जेक्ट बाइट्स (किंवा बाइट अॅरे) वाचू शकतो. तेच आहे — ते इतर कोणत्याही डेटा प्रकारांना समर्थन देत नाहीत.

परिणामी, या प्रवाहांना बाइट प्रवाह देखील म्हणतात .

प्रवाहांचे एक वैशिष्ट्य म्हणजे त्यांचा डेटा केवळ अनुक्रमे वाचला (किंवा लिहिला) जाऊ शकतो. तुम्ही प्रवाहाच्या मध्यभागी असलेला डेटा त्याच्या आधी येणारा सर्व डेटा वाचल्याशिवाय वाचू शकत नाही.

कीबोर्डवरील डेटा वाचणे हे वर्गाद्वारे कसे कार्य करते Scanner: तुम्ही कीबोर्डवरील डेटा क्रमाने, ओळीने वाचता. आपण एक ओळ वाचतो, नंतर पुढची ओळ, नंतर पुढची ओळ, आणि असेच. योग्यरित्या, ओळी वाचण्याच्या पद्धतीला म्हणतात nextLine().

वर डेटा लिहिणे OutputStreamदेखील क्रमाने होते. याचे उत्तम उदाहरण म्हणजे कन्सोल आउटपुट. तुम्ही एक ओळ आउटपुट करा, त्यानंतर दुसरी आणि दुसरी. हे अनुक्रमिक आउटपुट आहे. तुम्ही पहिली ओळ, नंतर दहावी आणि नंतर दुसरी आउटपुट करू शकत नाही. सर्व डेटा आउटपुट स्ट्रीमवर फक्त अनुक्रमे लिहिला जातो.

वर्ण प्रवाह

तुम्ही अलीकडेच शिकलात की स्ट्रिंग्स हा दुसरा सर्वात लोकप्रिय डेटा प्रकार आहे आणि खरंच आहे. अक्षरे आणि संपूर्ण तारांच्या रूपात बरीच माहिती दिली जाते. संगणक बाइट्स म्हणून सर्व काही पाठविण्यास आणि प्राप्त करण्यात उत्कृष्ट आहे, परंतु मानव इतके परिपूर्ण नाहीत.

या वस्तुस्थितीचा लेखाजोखा मांडताना, जावा प्रोग्रामरने आणखी दोन वर्ग लिहिले: Readerआणि Writer. वर्ग हा वर्ग Readerसमान आहे InputStream, परंतु त्याची read()पद्धत बाइट्स नाही तर वर्ण ( char) वाचते. वर्ग Writerवर्गाशी संबंधित आहे OutputStream. आणि वर्गाप्रमाणेच ते ( ) Readerवर्णांसह कार्य करते , बाइट्ससह नाही.char

जर आपण या चार वर्गांची तुलना केली तर आपल्याला खालील चित्र मिळेल:

बाइट्स (बाइट) वर्ण (चार)
डेटा वाचत आहे
InputStream
Reader
डेटा लिहित आहे
OutputStream
Writer

व्यवहारीक उपयोग

, InputStream, आणि वर्ग स्वतःच कोणीही थेट वापरत नाहीत, कारण ते कोणत्याही ठोस वस्तूंशी संबंधित नाहीत ज्यातून डेटा वाचला जाऊ शकतो (किंवा ज्यामध्ये डेटा लिहिला जाऊ शकतो) OutputStream. पण या चार वर्गांमध्ये भरपूर वंशज वर्ग आहेत जे खूप काही करू शकतात.ReaderWriter


2. InputStreamवर्ग

वर्ग InputStreamमनोरंजक आहे कारण तो शेकडो वंशज वर्गांसाठी पालक वर्ग आहे. त्याच्याकडे स्वतःचा कोणताही डेटा नाही, परंतु त्याच्याकडे अशा पद्धती आहेत ज्या त्याच्या सर्व व्युत्पन्न वर्गांना वारशाने मिळतात.

सर्वसाधारणपणे, स्ट्रीम ऑब्जेक्ट्ससाठी डेटा आंतरिकरित्या संग्रहित करणे दुर्मिळ आहे. प्रवाह हे डेटा वाचण्यासाठी/लिहण्याचे साधन आहे, परंतु स्टोरेज नाही. ते म्हणाले, अपवाद आहेत.

वर्गाच्या पद्धती InputStreamआणि त्याचे सर्व वंशज वर्ग:

पद्धती वर्णन
int read()
प्रवाहातून एक बाइट वाचतो
int read(byte[] buffer)
प्रवाहातील बाइट्सचा अ‍ॅरे वाचतो
byte[] readAllBytes()
प्रवाहातील सर्व बाइट्स वाचतो
long skip(long n)
nप्रवाहातील बाइट्स वगळते (ते वाचते आणि टाकून देते)
int available()
प्रवाहात किती बाइट्स शिल्लक आहेत ते तपासते
void close()
प्रवाह बंद करतो

चला या पद्धती थोडक्यात पाहू:

read()पद्धत

पद्धत प्रवाहातून एक बाइटread() वाचते आणि परत करते. रिटर्नच्या प्रकारामुळे तुम्ही गोंधळात पडू शकता . हा प्रकार निवडला गेला कारण मानक पूर्णांक प्रकार आहे. चे पहिले तीन बाइट्स शून्य असतील.intintint

read(byte[] buffer)पद्धत

या पद्धतीचा हा दुसरा प्रकार आहे read(). InputStreamहे तुम्हाला एकाच वेळी एक बाइट अॅरे वाचू देते . अ‍ॅरे जो बाइट्स संचयित करेल एक युक्तिवाद म्हणून पास करणे आवश्यक आहे. पद्धत एक संख्या परत करते — प्रत्यक्षात वाचलेल्या बाइट्सची संख्या.

समजा तुमच्याकडे 10 किलोबाइट बफर आहे आणि तुम्ही क्लास वापरून फाइलमधील डेटा वाचत आहात FileInputStream. फाइलमध्ये फक्त 2 किलोबाइट्स असल्यास, सर्व डेटा बफर अॅरेमध्ये लोड केला जाईल आणि पद्धत 2048 (2 किलोबाइट्स) क्रमांक देईल.

readAllBytes()पद्धत

खूप चांगली पद्धत. ते फक्त ते संपेपर्यंत सर्व डेटा वाचते InputStreamआणि सिंगल बाइट अॅरे म्हणून परत करते. लहान फाईल्स वाचण्यासाठी हे खूप सोपे आहे. मोठ्या फायली कदाचित मेमरीमध्ये शारीरिकदृष्ट्या फिट नसतील आणि पद्धत अपवाद करेल.

skip(long n)पद्धत

ही पद्धत तुम्हाला ऑब्जेक्टमधून प्रथम n बाइट्स वगळण्याची परवानगी देते InputStream. डेटा काटेकोरपणे क्रमाक्रमाने वाचल्यामुळे, ही पद्धत फक्त प्रवाहातील पहिले n बाइट वाचते आणि त्यांना टाकून देते.

प्रत्यक्षात वगळलेल्या बाइट्सची संख्या मिळवते (बाइट्स वगळण्यापूर्वी प्रवाह संपला असल्यास n).

int available()पद्धत

पद्धत अद्याप प्रवाहात शिल्लक राहिलेल्या बाइट्सची संख्या परत करते

void close()पद्धत

पद्धत close()डेटा प्रवाह बंद करते आणि त्याच्याशी संबंधित बाह्य संसाधने सोडते. एकदा स्ट्रीम बंद झाल्यानंतर, त्यातून कोणताही डेटा वाचता येणार नाही.

चला एक उदाहरण प्रोग्राम लिहू जे खूप मोठी फाइल कॉपी करते. readAllBytes()संपूर्ण फाइल मेमरीमध्ये वाचण्यासाठी आम्ही पद्धत वापरू शकत नाही . उदाहरण:

कोड नोंद
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);
FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = new byte[65536]; // 64Kb
   while (input.available() > 0)
   {
      int real = input.read(buffer);
      output.write(buffer, 0, real);
   }
}



InputStreamफाइलमधून वाचण्यासाठी
OutputStreamराइट टू फाइल

बफर ज्यामध्ये आम्ही डेटा वाचू
जोपर्यंत स्ट्रीममध्ये डेटा आहे तोपर्यंत

बफरमध्ये डेटा वाचा
बफरमधून दुसऱ्या स्ट्रीमवर डेटा लिहा

या उदाहरणात, आम्ही दोन वर्ग वापरले: फाईलमधील डेटा वाचण्यासाठीचा FileInputStreamएक वंशज आहे आणि फाइलमध्ये डेटा लिहिण्यासाठी वंशज आहे . दुसऱ्या वर्गाबद्दल आपण थोड्या वेळाने बोलू.InputStreamFileOutputStreamOutputStream

येथे आणखी एक मनोरंजक मुद्दा realव्हेरिएबल आहे. फाईलमधून डेटाचा शेवटचा ब्लॉक वाचला जातो, तेव्हा त्यात सहजपणे 64KB पेक्षा कमी डेटा असू शकतो. त्यानुसार, आपल्याला संपूर्ण बफर आउटपुट करणे आवश्यक आहे, परंतु त्यातील फक्त एक भाग - प्रथम realबाइट्स. पद्धतीत नेमके हेच घडते write().



3. Readerवर्ग

वर्ग Readerहा वर्गाचा संपूर्ण अॅनालॉग आहे InputStream. फक्त एकच फरक आहे की ते वर्णांसह कार्य करते ( char), बाइटसह नाही. वर्गाप्रमाणेच InputStream, Readerवर्ग स्वतःहून कुठेही वापरला जात नाही: हा शेकडो वंशज वर्गांसाठी पालक वर्ग आहे आणि त्या सर्वांसाठी सामान्य पद्धती परिभाषित करतो.

वर्गाच्या पद्धती Reader(आणि त्याचे सर्व वंशज वर्ग):

पद्धती वर्णन
int read()
charप्रवाहातून एक वाचतो
int read(char[] buffer)
charप्रवाहातील अॅरे वाचते
long skip(long n)
n charsप्रवाहात वगळते (ते वाचते आणि टाकून देते)
boolean ready()
प्रवाहात अजूनही काही शिल्लक आहे का ते तपासते
void close()
प्रवाह बंद करतो

पद्धती वर्गाच्या पद्धतींसारख्याच आहेत InputStream, जरी थोडे फरक आहेत.

int read()पद्धत

ही पद्धत charप्रवाहातून एक वाचते आणि ती परत करते. प्रकार charएक पर्यंत रुंद होतो int, परंतु परिणामाचे पहिले दोन बाइट नेहमी शून्य असतात.

int read(char[] buffer)पद्धत

या पद्धतीचा हा दुसरा प्रकार आहे read(). Readerहे तुम्हाला एकाच वेळी एक चार अॅरे वाचू देते . अ‍ॅरे जो वर्ण संग्रहित करेल तो वितर्क म्हणून पास करणे आवश्यक आहे. पद्धत एक संख्या मिळवते — प्रत्यक्षात वाचलेल्या वर्णांची संख्या.

skip(long n)पद्धत

ही पद्धत तुम्हाला ऑब्जेक्टमधील पहिले n वर्ण वगळण्याची परवानगी देते Reader. हे वर्गाच्या समान पद्धतीप्रमाणेच कार्य करते InputStream. प्रत्यक्षात वगळलेल्या वर्णांची संख्या मिळवते.

boolean ready()पद्धत

trueप्रवाहात न वाचलेले बाइट्स असल्यास परत येतात .

void close()पद्धत

पद्धत close()डेटा प्रवाह बंद करते आणि त्याच्याशी संबंधित बाह्य संसाधने सोडते. एकदा स्ट्रीम बंद झाल्यानंतर, त्यातून कोणताही डेटा वाचता येणार नाही.

तुलनेसाठी, एक प्रोग्राम लिहूया जो मजकूर फाइल कॉपी करतो:

कोड नोंद
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileReader reader = new FileReader(src);
FileWriter writer = new FileWriter(dest))
{
   char[] buffer = new char[65536]; // 128Kb
   while (reader.ready())
   {
      int real = reader.read(buffer);
      writer.write(buffer, 0, real);
   }
}



Readerफाइलमधून वाचण्यासाठी
Writerफाईल बफरवर लिहिण्यासाठी

ज्यामध्ये आम्ही डेटा वाचू
जोपर्यंत स्ट्रीममध्ये डेटा आहे तोपर्यंत

बफरमध्ये डेटा वाचा
बफरमधून दुसऱ्या प्रवाहावर डेटा लिहा