2011-01-10 13 views
14
ServletOutputStream output = response.getOutputStream(); 
output.write(byte[]); 

फ़ाइल को javax.servlet.ServletOutputStream में लिखने का सबसे प्रभावी तरीका क्या है?ServletOutputStream को फ़ाइल लिखने का सबसे प्रभावी तरीका

संपादित करें:

इस और अधिक प्रभावी अगर NIO इस्तेमाल किया गया था नहीं होगा?

+0

NIO एक जादुई गोली जो सब कुछ कब तेजी आधारित बनाता नहीं है। वास्तव में, यदि आप अपने कोड को अधिक _scalable_ बनाने की आवश्यकता है (उदाहरण के लिए अधिक कनेक्शन को संभालने वाले कम थ्रेड)। सिंगल थ्रेडेड कोड के लिए, आईओ लगभग हमेशा अच्छा या बेहतर होता है (इस नियम के लिए अपवाद फ़ाइल स्थानांतरण में फ़ाइल हो सकता है)। – jtahlborn

उत्तर

32
IOUtils.copy(in, out); 
out.flush(); 
//........... 
out.close(); // depends on your application 

कहाँ inFileInputStream और out है SocketOutputStream है। IOUtilsApache Commons में Commons IO मॉड्यूल से एक उपयोगिता है।

+6

+1, लेकिन दो नोट्स - यह "अपाचे कॉमन्स" है, और आप 'IOUtils.closeQuitely (..)' – Bozho

+0

@ बोझो का उपयोग कर सकते हैं जिसे इसे कई साल पहले जकार्ता कॉमन्स कहा जाता था :-) –

+0

जो काम नहीं करता है मैं, मैं उस कार्यक्षमता के लिए कॉमन्स आईओ जार जोड़ना नहीं चाहता हूं। – IAdapter

0

आप अपने आवेदन करने के लिए है कि जार में शामिल नहीं करना चाहते हैं तो आपको हाथ से कॉपी किया है। http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java?revision=1004358&view=markup:: बस यहाँ से विधि कार्यान्वयन कॉपी

private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; 

public static int copy(InputStream input, OutputStream output) throws IOException { 
    long count = copyLarge(input, output); 
    if (count > Integer.MAX_VALUE) { 
    return -1; 
    } 
    return (int) count; 
} 

public static long copyLarge(InputStream input, OutputStream output) 
    throws IOException { 
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 
    long count = 0; 
    int n = 0; 
    while (-1 != (n = input.read(buffer))) { 
    output.write(buffer, 0, n); 
    count += n; 
    } 
    return count; 
} 

अपने सहायक वर्गों में से एक में उन 2 तरीकों डाल दिया और आप के लिए तैयार हैं।

+1

एनआईओ का इस्तेमाल होने पर यह अधिक प्रभावी नहीं होगा? – IAdapter

+1

मेरे पास एनओओ के साथ मिश्रित परिणाम थे :)। यह बेहतर हो सकता है या ऐसा नहीं हो सकता है। कोड निश्चित रूप से थोड़ा अधिक जटिल है और आपको वास्तव में पर्याप्त सुनिश्चित करने के लिए अपनी मशीन पर परिणामों का परीक्षण करने की आवश्यकता है। कुछ कोड के लिए यहां देखें: http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/ –

+1

+1 ymmv, लेकिन मुझे nio बनाने में कठिनाई हुई है अच्छी पुरानी धाराओं की तुलना में संस्करण तेजी से –

3

सबसे पहले, यह सर्वलेट से संबंधित नहीं है। यह सामान्य रूप से जावा आईओ पर लागू होता है। आपके पास सिर्फ InputStream और OutputStream के बाद है।

जवाब देने के लिए के रूप में, आप केवल एक है जो इस बारे में सोचा नहीं कर रहे हैं। interwebs पर आप अन्य लोगों के बारे में सोचा, लेकिन परीक्षण करने के लिए प्रयास ले लिया पा सकते हैं/यह बेंचमार्क खुद को:

एक 256K बाइट सरणी के साथ

सामान्य तौर पर, एक FileChannel जिसे एक लिपटे ByteBuffer के माध्यम से पढ़ा जाता है और सीधे बाइट सरणी से लिखा जाता है वह सबसे तेज़ तरीका है। दरअसल, एनआईओ।

FileInputStream input = new FileInputStream("/path/to/file.ext"); 
FileChannel channel = input.getChannel(); 
byte[] buffer = new byte[256 * 1024]; 
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer); 

try { 
    for (int length = 0; (length = channel.read(byteBuffer)) != -1;) { 
     System.out.write(buffer, 0, length); 
     byteBuffer.clear(); 
    } 
} finally { 
    input.close(); 
} 
+0

पहला लिंक वास्तव में 8k 256K के बीच अंतर की प्रतिलिपि बनाने के लिए 8K बफर की अनुशंसा करता है। ऐसा लगता है कि अधिकांश फाइल सिस्टम अभी भी 4 केबी पेज और 4 केबी डिस्क क्लस्टर का उपयोग करते हैं। – AngerClown

+0

अंतर वास्तव में न्यूनतम है। ओपी हालांकि "प्रभावी तरीके" के लिए "कुशल तरीका" नहीं मांग रहा है। एक व्यस्त साइट के मामले में 8K अभी भी तेज है लेकिन कम स्मृति खपत है। – BalusC

+0

चैनल और चैनल का उपयोग करने के बारे में क्या। ट्रांसफर? – IAdapter

4

आपके पास ServletOutputStream है। एकमात्र तरीका जिसे आप लिख सकते हैं java.io. * के माध्यम से है। आप इस पर एनआईओ का उपयोग नहीं कर सकते हैं (Channels के साथ लपेटने के अलावा, जो व्यर्थ है: यह अभी भी OutputStream नीचे है और आप बस शीर्ष पर प्रसंस्करण जोड़ रहे हैं)। वास्तविक आई/ओ नेटवर्क बाध्य है, और अपने लेखन सर्वलेट कंटेनर से वैसे भी बफ़र किया जा रहा है (इतना है कि यह सामग्री-लंबाई निर्धारित कर सकते हैं) शीर्षक इसलिए यहाँ प्रदर्शन में तोड़ मरोड़ की तलाश में व्यर्थ है।

+0

आप एनओओ चैनल का उपयोग कर सकते हैं। – IAdapter

+8

@ 01: हां, यदि आप चैनलों का उपयोग करते हैं तो आप एनआईओ के चैनलों का उपयोग कर सकते हैं। NewChannel (आउटपुटस्ट्रीम)। जो एक चैनल में आउटपुट स्ट्रीम लपेटता है। यह अभी भी अंतर्निहित ByteArrayOutputStream से बात कर रहा है। इस स्थिति में कोई दक्षता लाभ नहीं है। यह व्यर्थ है। – EJP

+0

एनआईओ के चैनलों का उपयोग करके एनआईओ का उपयोग करना संभव है। –

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