2012-05-20 16 views
6

मुझे एनआईओ का उपयोग कर सर्वरसॉकेट पर ~ 100 एमबी डेटा स्थानांतरित करना है, लेकिन मुझे यह पता नहीं लगाया जा सकता कि हस्तांतरण की स्थिति को किसी भी स्थान पर स्थानांतरित करने के बिना इसे कैसे किया जाए।जावा - चैनलों पर बड़ी फ़ाइलों को स्थानांतरित करना - एनआईओ

मेरा पहला विचार फ़ाइल का आकार भेजना था, जाहिर है कि मैं उन बड़ी फ़ाइलों का आकार नहीं भेज सकता क्योंकि यह एक बार में रैम पर भी फिट नहीं होगा। फिर मैंने सोचा, क्यों न टिल कुछ भी नहीं स्थानांतरण नहीं प्राप्त होता है, लेकिन thats जब समस्या में आता है।

यहां तक ​​कि अगर मैं सर्वर तरफा डेटा लिख ​​रहा हूँ हर समय

 FileChannel fc = new FileInputStream(f).getChannel(); 
     ByteBuffer buffer = ByteBuffer.allocate(1024); 
     while(fc.read(buffer) > 0) { 
      buffer.flip(); 
      while(channel.write(buffer) > 0); 
      buffer.clear(); 
     } 

लेकिन क्योंकि वहाँ टूट होना जरूरी फ़ाइल हस्तांतरण में डेटा को लगातार पढ़ने और कुछ भी उपलब्ध होने पर तोड़ना बुरा विचार था।

मैं यह नहीं समझ सकता कि मैं क्लाइंट को संभावित रूप से कैसे बता सकता हूं अगर डेटा के प्रत्येक टुकड़े को ओपोड आदि के साथ नए पैकेट के रूप में भेजने के बिना अभी भी डेटा उपलब्ध है, या यह भी संभव है?

मैं भी अगर थेरेस बेहतर तरीका

नीचे
while(channel.write(buffer) > 0); 
+0

मैंने इसका हिस्सा जवाब दिया है, लेकिन मुझे यह कहना होगा कि मुझे समझ में नहीं आता कि "कुछ समय में फ़ाइल स्थानांतरण में ब्रेक होना चाहिए" और "डेटा को लगातार पढ़ना और कुछ भी उपलब्ध नहीं होने पर तोड़ना बुरा विचार था "। कृपया समझाएँ। – EJP

उत्तर

3

सही बफ़र्स के माध्यम से चैनलों कॉपी करने के लिए जिस तरह से इस प्रकार है:

while (in.read(buffer) >= 0 || buffer.position() > 0) 
{ 
    buffer.flip(); 
    out.write(buffer); 
    buffer.compact(); 
} 

यह सब कोने पढ़ लंबाई सहित मामलों का ख्याल रखता है = लिखने की लंबाई और इनपुट के अंत में बचे डेटा होने!।

एनबी जो ब्लॉकिंग मोड के लिए है। यदि आप गैर-अवरुद्ध मोड में हैं तो आपको select() लूप पर वापस जाना चाहिए यदि पढ़ा() या लिखना() शून्य देता है।

+0

इच्छा है कि मैं कई उत्तरों स्वीकार कर सकता हूं, क्योंकि मुझे यकीन नहीं है कि यह स्वीकार किसके लिए है। विज़ीर ने मुझे एक आदर्श समाधान दिया लेकिन आपने इसे पूरा किया। मैं वर्तमान में लगभग सटीक कोड का उपयोग कर रहा हूं और यह पूरी तरह से काम कर रहा है। आप दोनों के लिए बहुत बहुत धन्यवाद। फिर भी मुझे यकीन नहीं है कि कॉम्पैक्ट ऑपरेशन क्या करता है, लेकिन मुझे लगता है कि यह समाशोधन से बेहतर होना चाहिए। एक बार फिर धन्यवाद! – Ruuhkis

+1

@Ruuhkis 'कॉम्पैक्ट() 'लिखा गया सामान हटा देता है लेकिन लिखे गए कुछ भी छोड़ देता है। यदि आप 'स्पष्ट() 'का उपयोग करते हैं तो आप पढ़ने की लंबाई में डेटा हानि का जोखिम उठा रहे हैं! = लिखने की लंबाई, जो किसी भी समय हो सकती है। – EJP

+0

धन्यवाद, यह कुछ अच्छी सलाह है। – Ruuhkis

4

हो सकता है कि आप इस के लिए देख रहे हैं पूरे बफर भेजने के लिए सोच रहा हूँ:

channel.transferFrom(0, fc.size(), fc); 
+0

वाह, मैं इसे कैसे याद कर सकता था? मैं कल कोशिश करूँगा और आशा करता हूं कि यह ठीक काम करता है तो आपका जवाब स्वीकार करने के लिए आ जाएगा। – Ruuhkis

+0

@Ruuhkis कृपया ध्यान दें कि आपको इस विधि को लूप में कॉल करने की आवश्यकता है, क्योंकि यह पूरी लंबाई को एक आमंत्रण में स्थानांतरित करने की गारंटी नहीं है। मेरा जवाब भी देखें। – EJP

+0

कृपया ईजेपी के उत्तर विज़ीर को मेरी टिप्पणी पढ़ें। – Ruuhkis

0

आप सॉकेट पर निर्भर नहीं कर सकते, तो खुले रहने के लिए, आपके प्रोटोकॉल में रिकवरी-एंड-जारी तंत्र बनाने के आसपास कोई रास्ता नहीं है। क्लाइंट को यह बताने के लिए कि कितने बाइट्स उम्मीद कर सकते हैं, आप File.length का उपयोग कर स्मृति में इसे पढ़ने के बिना फ़ाइल का आकार पा सकते हैं।

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