1. डेटा स्ट्रीम

शायद ही कोई कार्यक्रम अपने आप में एक द्वीप के रूप में मौजूद होता है। कार्यक्रम आमतौर पर किसी तरह "बाहरी दुनिया" के साथ बातचीत करते हैं। यह कुंजीपटल से डेटा पढ़ने, संदेश भेजने, इंटरनेट से पृष्ठ डाउनलोड करने, या इसके विपरीत, दूरस्थ सर्वर पर फ़ाइलें अपलोड करने के माध्यम से हो सकता है।

हम इन सभी व्यवहारों को एक शब्द में संदर्भित कर सकते हैं: प्रोग्राम और बाहरी दुनिया के बीच डेटा का आदान-प्रदान । रुकिए, यह सिर्फ एक शब्द नहीं है।

बेशक, डेटा एक्सचेंज को ही दो भागों में विभाजित किया जा सकता है: डेटा प्राप्त करना और डेटा भेजना। उदाहरण के लिए, आप किसी ऑब्जेक्ट का उपयोग करके कीबोर्ड से डेटा पढ़ते हैं Scanner— यह डेटा प्राप्त कर रहा है। और आप एक आदेश का उपयोग करके स्क्रीन पर डेटा प्रदर्शित करते हैं System.out.println()— यह डेटा भेज रहा है।

प्रोग्रामिंग में, डेटा एक्सचेंज का वर्णन करने के लिए "स्ट्रीम" शब्द का उपयोग किया जाता है। वह शब्द कहां से आया?

वास्तविक जीवन में, आपके पास पानी की धारा या चेतना की धारा हो सकती है। प्रोग्रामिंग में, हमारे पास डेटा स्ट्रीम हैं ।

धाराएँ एक बहुमुखी उपकरण हैं। वे कार्यक्रम को कहीं से भी डेटा प्राप्त करने की अनुमति देते हैं (इनपुट स्ट्रीम) और कहीं भी डेटा भेजते हैं (आउटपुट स्ट्रीम)। इस प्रकार, दो प्रकार हैं:

  • डेटा प्राप्त करने के लिए एक इनपुट स्ट्रीम है
  • डेटा भेजने के लिए एक आउटपुट स्ट्रीम है

धाराओं को 'मूर्त' बनाने के लिए, जावा के रचनाकारों ने दो वर्ग लिखे: InputStreamऔर OutputStream

कक्षा InputStreamमें एक read()विधि है जो आपको इससे डेटा पढ़ने देती है। और OutputStreamकक्षा में एक write()विधि है जो आपको डेटा लिखने देती है। उनके पास अन्य तरीके भी हैं, लेकिन उस पर और बाद में।

बाइट स्ट्रीम

हम किस तरह के डेटा की बात कर रहे हैं? यह कौन सा प्रारूप लेता है? दूसरे शब्दों में, ये वर्ग किस डेटा प्रकार का समर्थन करते हैं?

ये सामान्य वर्ग हैं, इसलिए वे सबसे सामान्य डेटा प्रकार - byte. एक OutputStreamबाइट्स (और बाइट सरणियाँ) लिख सकता है, और एक InputStreamवस्तु बाइट्स (या बाइट सरणियाँ) पढ़ सकती है। बस इतना ही — वे किसी अन्य डेटा प्रकार का समर्थन नहीं करते हैं।

नतीजतन, इन धाराओं को बाइट स्ट्रीम भी कहा जाता है ।

धाराओं की एक विशेषता यह है कि उनका डेटा केवल क्रमिक रूप से पढ़ा (या लिखा) जा सकता है। आप स्ट्रीम के बीच में आने वाले सभी डेटा को पढ़े बिना डेटा को स्ट्रीम के बीच से नहीं पढ़ सकते हैं।

इस तरह से कीबोर्ड से डेटा पढ़ना Scannerकक्षा के माध्यम से काम करता है: आप कीबोर्ड से क्रमिक रूप से डेटा पढ़ते हैं, लाइन से लाइन। हम एक पंक्ति पढ़ते हैं, फिर अगली पंक्ति, फिर अगली पंक्ति, और इसी तरह। उपयुक्त रूप से, पंक्तियों को पढ़ने की विधि कहलाती है nextLine()

a को डेटा लिखना 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एक बार में पढ़ने देता है। बाइट्स को स्टोर करने वाली सरणी को तर्क के रूप में पारित किया जाना चाहिए। विधि एक संख्या लौटाती है - बाइट्स की संख्या वास्तव में पढ़ी जाती है।

FileInputStreamमान लें कि आपके पास 10 किलोबाइट बफर है और आप कक्षा का उपयोग कर फ़ाइल से डेटा पढ़ रहे हैं। यदि फ़ाइल में केवल 2 किलोबाइट हैं, तो सभी डेटा को बफर ऐरे में लोड किया जाएगा, और विधि 2048 (2 किलोबाइट) संख्या वापस कर देगी।

readAllBytes()तरीका

बहुत अच्छा तरीका है। यह केवल समाप्त होने तक सभी डेटा को पढ़ता है InputStreamऔर इसे एक बाइट सरणी के रूप में लौटाता है। छोटी फाइलों को पढ़ने के लिए यह बहुत उपयोगी है। बड़ी फ़ाइलें भौतिक रूप से स्मृति में फिट नहीं हो सकती हैं, और विधि अपवाद फेंक देगी।

skip(long n)तरीका

InputStreamयह विधि आपको ऑब्जेक्ट से पहले एन बाइट छोड़ने की अनुमति देती है । चूंकि डेटा सख्ती से अनुक्रमिक रूप से पढ़ा जाता है, इसलिए यह विधि स्ट्रीम से पहले एन बाइट्स को पढ़ती है और उन्हें छोड़ देती है।

वास्तव में छोड़े गए बाइट्स की संख्या लौटाता है (यदि 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का एक वंशज है InputStream, और एक फ़ाइल में डेटा लिखने के लिए FileOutputStreamएक वंशज है । OutputStreamहम दूसरी कक्षा के बारे में थोड़ी देर बाद बात करेंगे।

यहाँ एक और दिलचस्प बिंदु 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धारा से एक को पढ़ती है और उसे वापस कर देती है। प्रकार chara तक विस्तृत होता है int, लेकिन परिणाम के पहले दो बाइट हमेशा शून्य होते हैं।

int read(char[] buffer)तरीका

यह विधि का दूसरा रूप है read()Readerयह आपको एक बार में एक चार सरणी पढ़ने देता है । वर्णों को संग्रहीत करने वाली सरणी को एक तर्क के रूप में पारित किया जाना चाहिए। विधि एक संख्या लौटाती है - वास्तव में पढ़े गए वर्णों की संख्या।

skip(long n)तरीका

Readerयह विधि आपको ऑब्जेक्ट से पहले n वर्णों को छोड़ने की अनुमति देती है । यह ठीक उसी तरह काम करता है जैसे 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के लिए फ़ाइल में लिखने के लिए

बफ़र जिसमें हम डेटा को
तब तक पढ़ेंगे जब तक स्ट्रीम में डेटा है

एक बफर में डेटा पढ़ें
बफर से दूसरी स्ट्रीम में डेटा लिखें