2015-11-29 4 views
22

मैंने निम्नलिखित कोड लिखा है जोफ़ाइल में 4000 बाइट्स 0s लिखता है। फिर, मैंने एक ही फाइल को एक ही समय में 1000 बाइट्स के टुकड़ों में पढ़ा।ऑब्जेक्टइनपुटस्ट्रीम के साथ एक समय में केवल 1024 बाइट्स क्यों पढ़ सकता हूं?

FileOutputStream output = new FileOutputStream("test.txt"); 
ObjectOutputStream stream = new ObjectOutputStream(output); 

byte[] bytes = new byte[4000]; 

stream.write(bytes); 
stream.close(); 

FileInputStream input = new FileInputStream("test.txt"); 
ObjectInputStream s = new ObjectInputStream(input); 


byte[] buffer = new byte[1000]; 
int read = s.read(buffer); 

while (read > 0) { 
    System.out.println("Read " + read); 
    read = s.read(buffer); 
} 

s.close(); 

मुझे उम्मीद है कि 1000 बाइट चार बार पढ़ना है।

Read 1000 
Read 1000 
Read 1000 
Read 1000 

हालांकि, वास्तव में क्या होता है कि मुझे लगता है कि मुझे हर 1024 बाइट्स "बेहतर" की कमी के लिए "रोका गया" लगता है।

Read 1000 
Read 24 
Read 1000 
Read 24 
Read 1000 
Read 24 
Read 928 

यदि मैं 1024 से अधिक बाइट्स पढ़ने की कोशिश करता हूं, तो मुझे 1024 बाइट्स पर कैप्ड किया जाता है। अगर मैं 1024 बाइट से कम पढ़ने की कोशिश करता हूं, तो मुझे अभी भी 1024 बाइट मार्क पर रोकना होगा।

हेक्साडेसिमल में आउटपुट फ़ाइल test.txt का निरीक्षण करने पर, मैंने देखा 5 गैर शून्य बाइट्स 7A 00 00 04 00 1029 अलग बाइट्स की एक दृश्य तथ्य यह है कि मैं फाइल करने के लिए केवल 0s लिखा है के बावजूद है कि वहाँ,। Here is the output from my hex editor. (प्रश्न में फिट होने में बहुत लंबा होगा।)

तो मेरा सवाल है: जब मैं पूरी तरह से 0 लिखा है तो ये पांच बाइट मेरी फ़ाइल में क्यों दिख रहे हैं? क्या इन 5 बाइट्स में विराम के साथ कुछ करने के लिए कुछ 1024 बाइट होता है? यह जरूरी क्यों है?

+2

'इनपुटस्ट्रीम.read (बाइट []) 'गारंटी नहीं देता है कि यह जितना संभव हो सके पढ़ता है। आपके द्वारा वर्णित "संक्षिप्त पढ़ने" व्यवहार पूरी तरह से कानूनी है, यहां तक ​​कि फ़ाइल-आधारित इनपुट के लिए भी। तो यदि आप पूरे बफर को पढ़ना चाहते हैं, तो 'DataInput.readFully (बाइट [])' का उपयोग करें। – Nayuki

+0

@NayukiMinase मैं समझता हूं। हालांकि, क्या आप कृपया बता सकते हैं कि यह 1024 बाइट चिह्न पर क्यों रुकता है? उदाहरण के लिए, यह मुझे समझ में आएगा कि अगर मैं केवल 1024 बाइट्स पर पढ़ सकता हूं, और मेरा परिणाम 1024, 1024, 1024, 928 होगा। लेकिन मैं उलझन में हूं कि यह पहले 1000 बाइट्स को ठीक क्यों पढ़ता है, लेकिन फिर यह फिर से जारी रखने से पहले अगले 24 बाइट्स पढ़ सकता है। यह पूरी तरह से मनमाना लगता है? या इसके लिए कोई कारण है? – Zsw

+0

मुझे नहीं पता। लेकिन मैं आपके द्वारा वर्णित 5-बाइट अनुक्रम से परेशान हूं, क्योंकि न तो ऑब्जेक्ट इनपुटप्रीम के लिए जावाडोक और न ही ऑब्जेक्टऑटपुटस्ट्रीम बाइट एरे के स्वरूपण के बारे में कुछ भी कहता है। – Nayuki

उत्तर

17

ऑब्जेक्ट स्ट्रीम एक आंतरिक 1024-बाइट बफर का उपयोग करते हैं, और ब्लॉक डेटा मार्करों की अध्यक्षता वाली धारा के ब्लॉक में उस आकार के हिस्सों में आदिम डेटा लिखते हैं, जो अनुमान लगाते हैं कि 0x7A 32-बिट लंबाई के बाद शब्द (या 0x77 के बाद 8-बिट लंबाई शब्द)। तो आप केवल अधिकतम 1024 बाइट्स पढ़ सकते हैं।

असली सवाल यह है कि आप बाइट्स को पढ़ने और लिखने के लिए ऑब्जेक्ट स्ट्रीम का उपयोग क्यों कर रहे हैं। Buffered धाराओं का प्रयोग करें। फिर बफरिंग आपके नियंत्रण में है, और आकस्मिक रूप से वहां शून्य स्थान ओवरहेड है, ऑब्जेक्ट स्ट्रीम के विपरीत जिसमें स्ट्रीम हेडर और टाइप कोड हैं।

एनबी धारावाहिक डेटा टेक्स्ट नहीं है और इसे .txt नाम की फ़ाइलों में संग्रहीत नहीं किया जाना चाहिए।

+1

ठीक है, मैं ऑब्जेक्ट स्ट्रीम का उपयोग क्यों कर रहा हूं, यह इतना था क्योंकि मैं ऑब्जेक्ट्स के साथ-साथ उसी स्ट्रीम में बाइट्स को क्रमबद्ध करने की कोशिश कर रहा था। क्या यह दो अलग-अलग धाराओं को बनाने और उन्हें अलग करने के लिए बेहतर अभ्यास है? क्या ऑब्जेक्ट स्ट्रीम हेडर के साथ संघर्ष नहीं होगा? – Zsw

+1

बेशक यह होगा। आपको निश्चित रूप से एक ही स्ट्रीम का उपयोग करना चाहिए, और यदि इसमें वस्तुएं हैं तो आपके पास ऑब्जेक्ट स्ट्रीम का उपयोग करने के अलावा कोई विकल्प नहीं है। – EJP

4

मैं तुम्हें एक try-with-resources Statement उपयोग करते हैं, अपने संसाधनों को बंद करने को संभालने BufferedInputStream और BufferedOutputStream साथ बफरिंग जोड़ें और फिर writeObject और readObject का उपयोग अपने byte[] क्रमानुसार करने के लिए सुझाव देते हैं। कुछ की तरह,

try (OutputStream output = new BufferedOutputStream(// 
     new FileOutputStream("test.txt"), 8192); // 
     ObjectOutputStream stream = new ObjectOutputStream(output)) { 
    byte[] bytes = new byte[4000]; 

    stream.writeObject(bytes); 
} catch (IOException ioe) { 
    ioe.printStackTrace(); 
} 

और उसके बाद की तरह

try (InputStream input = new BufferedInputStream(// 
     new FileInputStream("test.txt"), 8192); // 
     ObjectInputStream s = new ObjectInputStream(input)) { 
    byte[] bytes = (byte[]) s.readObject(); 
} catch (IOException | ClassNotFoundException ioe) { 
    ioe.printStackTrace(); 
} 

पढ़ने के लिए आंशिक सरणियों शामिल देखते हैं, तो आप लंबाई जोड़ने की आवश्यकता होगी। आप दूसरी तरफ stream.writeInt(len); और int len = stream.readInt(); का उपयोग कर सकते हैं।

8

ObjectOutputStream और ObjectInputStream ऑब्जेक्ट्स के क्रमबद्ध करने के लिए उपयोग की जाने वाली विशेष धाराएं हैं।

लेकिन जब आप stream.write(bytes); करते हैं तो आप 412 बाइट लिखने के लिए ObjectOutputStream नियमित स्ट्रीम के रूप में उपयोग करने की कोशिश कर रहे हैं, एक सरणी-बाइट ऑब्जेक्ट लिखने के लिए नहीं। जब डेटा ObjectOutputStream पर लिखा जाता है तो उन्हें विशेष रूप से संभाला जाता है।

documentation of ObjectOutputStream से:

(। जोर मेरा)

आदिम डेटा, serializable खेतों और externalizable डेटा को छोड़कर, ब्लॉक डेटा रिकॉर्ड में ObjectOutputStream लिखा है। एक ब्लॉक डेटा रिकॉर्ड एक शीर्षलेख और डेटा से बना है। ब्लॉक डेटा हेडर में शीर्षलेख का पालन करने के लिए मार्कर और बाइट्स की संख्या होती है। अभिसरण आदिम डेटा लिखने को एक ब्लॉक-डेटा रिकॉर्ड में विलय कर दिया जाता है। ब्लॉक-डेटा रिकॉर्ड के लिए उपयोग किया जाने वाला अवरोधक कारक 1024 बाइट्स होगा। प्रत्येक ब्लॉक-डेटा रिकॉर्ड 1024 बाइट तक भर जाएगा, या ब्लॉक-डेटा मोड को समाप्त होने पर भी लिखा जा सकता है।

मुझे उम्मीद है कि यह स्पष्ट है कि आप यह व्यवहार क्यों प्राप्त कर रहे हैं।

मैं सुझाव है कि आप या तो BufferedOutputStream बजाय ObjectOutputStream, का उपयोग करें या, क्या तुम सच में ObjectOutputStream उपयोग करना चाहते हैं, तो writeObject() बजाय write() का उपयोग करें। संबंधित इनपुट पर लागू होता है।

संबंधित मुद्दे