2011-10-24 15 views
5

के लिए की एक ही राशि नहीं पढ़ता अच्छा है या बुरा मैं बिना किसी समस्या के निम्नलिखित की तरह कोड का उपयोग किया गया है:जावा: InputStream से पढ़ें हमेशा डेटा

ZipFile aZipFile = new ZipFile(fileName); 
InputStream zipInput = aZipFile.getInputStream(name); 
int theSize = zipInput.available(); 
byte[] content = new byte[theSize]; 
zipInput.read(content, 0, theSize); 

मैं इसे इस्तेमाल किया है प्राप्त करने की इस तर्क (उपलब्ध आकार और सीधे बाइट बफर को पढ़ना) File I/O के लिए किसी भी मुद्दे के बिना और मैंने इसे ज़िप फ़ाइलों के साथ भी उपयोग किया।

लेकिन हाल ही में मैंने एक मामले में कदम रखा कि zipInput.read(content, 0, theSize); वास्तव में theSize उपलब्ध है कि 3 बाइट कम पढ़ता है।

और चूंकि कोड मैं 3 पिछले बाइट्स
लापता और बाद में कार्यक्रम ठीक से काम नहीं कर सकते हैं (फ़ाइल एक बाइनरी फ़ाइल है) के साथ फ़ाइल को पढ़ने लंबाई zipInput.read(content, 0, theSize); द्वारा वापस जाँच करने के लिए एक पाश में नहीं है।

बड़े आकार की विभिन्न ज़िप फ़ाइलों के साथ पर्याप्त अजीब 1075 बाइट्स (मेरे मामले में समस्याग्रस्त ज़िप प्रविष्टि 867 बाइट्स है) कोड ठीक काम करता है!

मैं समझता हूं कि कोड का तर्क शायद "सर्वश्रेष्ठ" नहीं है, लेकिन मुझे अचानक यह समस्या क्यों मिल रही है?

और अगर मैं तुरंत एक बड़ी ज़िप प्रविष्टि के साथ प्रोग्राम चलाता हूं तो यह कैसे काम करता है?

किसी भी इनपुट अत्यधिक स्वागत

धन्यवाद

उत्तर

7

InputStreamread एपीआई डॉक्स से है:

का प्रयास लेन बाइट्स के रूप में कई को पढ़ने के लिए किया जाता है, लेकिन एक छोटी संख्या हो सकता है पढ़ें।

... और:

रिटर्न: बफर में पढ़े गए बाइट की कुल संख्या, या -1 अगर वहाँ कोई और अधिक डेटा क्योंकि धारा के अंत तक पहुँच गया है।

दूसरे शब्दों में, जब तक पढ़ने विधि रिटर्न -1 वहाँ अभी भी और अधिक डेटा को पढ़ने के लिए उपलब्ध है, लेकिन आप गारंटी नहीं दे सकते कि readबिल्कुल बाइट्स की निर्धारित संख्या पढ़ा जाएगा। बाइट्स की निर्दिष्ट संख्या ऊपरी बाउंडअधिकतम डेटा पढ़ने की मात्रा का वर्णन करती है।

+0

मुझे इस बारे में पता है। यही कारण है कि मैंने उल्लेख किया कि मेरा दृष्टिकोण अच्छा नहीं है। फिर भी मैं इस व्यवहार को समझने की कोशिश कर रहा हूं, एक छोटी फ़ाइल में पिछले 3 बाइट्स को याद करने के लिए, लेकिन बड़ी फ़ाइलों में कोई समस्या नहीं है – Cratylus

+3

@ user384706: समझना कि विशिष्ट व्यवहार कोई लक्ष्य नहीं देता है: यह कार्यान्वयन-निर्भर है और कई कारकों के आधार पर आपका कोड किसी भी तरीके से गलत हो सकता है। यह समझना महत्वपूर्ण है कि आपका कोड सामान्य रूप से गलत क्यों हो सकता है और इसे कैसे ठीक किया जा सकता है। –

2

available() का उपयोग करने की गारंटी नहीं है कि यह कुल उपलब्ध बाइट end of stream पर गिना जाता है।
जावा InputStream's available() method का संदर्भ लें। ऐसा नहीं है कि

बाइट्स कि इस इनपुट धारा से इस इनपुट स्ट्रीम के लिए एक विधि के अगले मंगलाचरण से रोके बिना पढ़ा जा सकता है (या आप छोड़) की संख्या का अनुमान देता है कहते हैं। अगला आविष्कार एक ही धागा या दूसरा धागा हो सकता है। इस कई बाइट्स का एक एकल पठन या छोड़ना अवरुद्ध नहीं होगा, लेकिन कम बाइट्स को पढ़ या छोड़ सकता है।

ध्यान दें कि InputStream के कुछ कार्यान्वयन धारा में बाइट्स की कुल संख्या वापस कर देंगे, कई लोग नहीं करेंगे। इस धारा में सभी डेटा रखने के उद्देश्य से बफर आवंटित करने के लिए इस विधि के वापसी मूल्य का उपयोग करना कभी भी सही नहीं होता है।

ZipFile aZipFile = new ZipFile(fileName); 
InputStream zipInput = aZipFile.getInputStream(caImport); 
int available = zipInput.available(); 
byte[] contentBytes = new byte[ available ]; 
while (available != 0) 
{ 
    zipInput.read(contentBytes); 
    // here, do what ever you want 
    available = dis.available(); 
} // while available 
... 

इस इनपुट फ़ाइलों के सभी आकारों पर यकीन है कि के लिए काम करता है: आपकी समस्या के लिए

एक उदाहरण समाधान इस प्रकार हो सकता है।

+4

कृपया ** ** के लिए 'उपलब्ध' का उपयोग न करें **! यह मदद नहीं करता है और केवल आपके कोड को और अधिक नाजुक बनाता है। बस तब तक पढ़ें जब तक आपको कोई और सामग्री न मिल जाए। –

+1

@ जोचिम: तो जब उपलब्ध 'उपलब्ध' होता है? – Cratylus

+1

@ user384706: एकमात्र मान्य उपयोग जो * मुझे पता है कि यदि आप एक धीमी धारा (उदाहरण के लिए एक सॉकेट) देखना चाहते हैं तो * यदि * कोई डेटा उपलब्ध है (और यदि कुछ भी उपलब्ध नहीं है, तो कुछ करें अन्य)। इसका कारण यह है कि यह किसी और चीज के लिए उपयोगी नहीं है, यह स्वाभाविक रूप से उग्र प्रकृति है (यानी जब तक आप वास्तविक 'पढ़ा'() 'संख्या पहले से ही बदल चुके हैं)। –

0

यह करने के लिए धौंकनी के रूप में होना चाहिए सबसे अच्छा तरीका है:

public static byte[] readZipFileToByteArray(ZipFile zipFile, ZipEntry entry) 
    throws IOException { 
    InputStream in = null; 
    try { 
     in = zipFile.getInputStream(entry); 
     return IOUtils.toByteArray(in); 
    } finally { 
     IOUtils.closeQuietly(in); 
    } 
} 

जहां IOUtils.toByteArray (में) विधि EOF जब तक पढ़ने और फिर बाइट सरणी लौट रहता है।

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