2012-08-13 15 views
5

मैं आने वाले HttpServletRequest (नीचे 'अनुरोध') से अनुरोध स्ट्रीम (gzipped डेटा युक्त) पढ़ने के लिए कुछ लिख रहा हूं, हालांकि ऐसा लगता है कि सामान्य इनपुटस्ट्रीम रीड विधि वास्तव में सभी सामग्री को नहीं पढ़ती है?इनपुटस्ट्रीम.read (बाइट [], 0 लंबाई) जल्दी बंद हो जाता है?

मेरे कोड था:

InputStream requestStream = request.getInputStream(); 
if ((length = request.getContentLength()) != -1) 
{ 
    received = new byte[length]; 
    requestStream.read(received, 0, length); 
} 
else 
{ 
    // create a variable length list of bytes 
    List<Byte> bytes = new ArrayList<Byte>(); 

    boolean endLoop = false; 
    while (!endLoop) 
    { 
     // try and read the next value from the stream.. if not -1, add it to the list as a byte. if 
     // it is, we've reached the end. 
     int currentByte = requestStream.read(); 
     if (currentByte != -1) 
      bytes.add((byte) currentByte); 
     else 
      endLoop = true; 
    } 
    // initialize the final byte[] to the right length and add each byte into it in the right order. 
    received = new byte[bytes.size()]; 
    for (int i = 0; i < bytes.size(); i++) 
    { 
     received[i] = bytes.get(i); 
    } 
} 

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

तो ऐसा लगता है कि मैं अभी उस परिवर्तन के साथ अकेले अपना कोड छोड़ सकता हूं, लेकिन क्या किसी को कोई विचार है कि सामान्य 'पढ़ा' (बाइट [], int, int) 'विधि क्यों पढ़ना बंद कर दिया? विवरण कहता है कि फ़ाइल का अंत मौजूद होने पर यह रुक सकता है। क्या यह हो सकता है कि gzipped डेटा बस उस बाइट्स को शामिल करने के लिए हुआ जो उसके लिए हस्ताक्षर जैसा दिखता है?

+0

बीटीडब्ल्यू, आप [GZIPInputStream] (http://docs.oracle.com/javase/7/docs/api/java/util/zip/GZIPInputStream.html) पर एक नज़र डालना चाहते हैं। सब कुछ एक बाइट सरणी में पढ़ने के बजाय और फिर डेटा को अलग-अलग डंप्रेस करने के बजाय आप केवल कच्चे इनपुटस्ट्रीम को GZIPInputStream में लपेट सकते हैं और सीधे डिकंप्रेस्ड डेटा पढ़ सकते हैं। –

+0

आह, कारण हम सीधे ऐसा नहीं करते हैं क्योंकि कभी-कभी हमें अन्य सिस्टम से प्राप्त इनपुट वास्तव में gzipped नहीं होता है, हालांकि यह माना जाता है ... :) –

उत्तर

8

सभी बाइट्स प्राप्त करने के लिए आपको शीर्ष पर while लूप जोड़ने की आवश्यकता है। धारा यह कर सकते हैं के रूप में कई बाइट्स पढ़ने के लिए प्रयास करेगा, लेकिन यह एक ही बार में len बाइट्स वापस जाने के लिए आवश्यक नहीं है:

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

if ((length = request.getContentLength()) != -1) 
{ 
    received = new byte[length]; 
    int pos = 0; 
    do { 
     int read = requestStream.read(received, pos, length-pos); 

     // check for end of file or error 
     if (read == -1) { 
      break; 
     } else { 
      pos += read; 
     } 
    } while (pos < length); 
} 

संपादित करें: तय है।

+0

आह, यह बहुत अच्छा काम करता है, धन्यवाद! –

+1

वैसे, आपको डेटा को पढ़ने के लिए अनुरोध लंबाई का उपयोग नहीं करना चाहिए। पढ़ा() विधि एक -1 लौटाएगी जब यह इनपुट के अंत तक पहुंच जाएगी। यह आपका संकेतक होना चाहिए कि डेटा समाप्त हो गया है या नहीं। – Matt

1

आपको यह देखने की ज़रूरत है कि बफर कितना भरा था। यह आपको कम से कम एक बाइट देने की गारंटी देता है।

शायद आप जो चाहते थे DataInputStream.readFully();

+0

हां, मैंने अन्य पोस्टों पर इसके बारे में टिप्पणी देखी है इस मुद्दे के बारे में - यह शायद मेरे लिए भी काम करेगा, लेकिन इसे ठीक करते समय यह आउटपुट पढ़ने का एक तरीका रखने के लिए और अधिक समझदार लग रहा था :) केवल एक बात यह है कि मुझे यकीन नहीं है कि यह अंतर्निहित विधि से धीमा होगा या नहीं ... हम केवल आने वाले अनुरोधों की अपेक्षा कर रहे हैं (20k तक शायद?) हालांकि इससे कोई फर्क नहीं पड़ता। 'पढ़ने' विधि का आउटपुट वास्तव में कितना पढ़ता है इसके संदर्भ में सही था - यानी 11k बाइट इनपुट के लिए यह बताएगा कि यह केवल 7k बाइट्स पढ़ता है। मुझे यकीन नहीं है कि ऐसा क्यों हुआ! –

+2

यह आपको उतना अधिक डेटा उपलब्ध कराता है ताकि आप कुछ और पढ़ने से पहले इसे संसाधित कर सकें। यदि डेटा बहुत बड़ा है तो एएसपी प्रोसेस करने से पहले यह सभी डेटा की प्रतीक्षा करने से पहले अधिक कुशल है। –

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