2008-10-01 9 views
30

ठीक है बंद करना, मैं निम्नलिखित (चर नाम बदल दिया गया है) कर दिया गया है। मैं यह देखने का फैसला करता हूं कि अंत में {} ब्लॉक के साथ कुछ भी किया जा सकता है, और फिर मैं देखता हूं, ओह हाँ, बंद() IOException फेंक सकता है। लोगों को यहां क्या करना चाहिए? जावा पुस्तकालयों ने बहुत से चेक अपवाद फेंक दिए हैं।एक जावा FileInputStream

+0

'fis' संभवतः उस बिंदु पर शून्य नहीं हो सकता है जिसका आप परीक्षण कर रहे हैं। यह अनुपलब्ध 'आखिरकार' ब्लॉक में शून्य हो सकता है जहां आपको इसका परीक्षण करना चाहिए और इसे बंद करना चाहिए। लेकिन सवाल 'प्रयास-संसाधनों' वाक्यविन्यास की शुरूआत के बाद अप्रचलित है। – EJP

+0

मैंने तदनुसार कोड को संशोधित किया है ताकि लोग गुमराह न हों। –

उत्तर

38

जावा 7 और try-with-resources ऊपर इस्तेमाल किया जाना चाहिए:

try (InputStream in = new FileInputStream(file)) { 
    // TODO: work 
} catch (IOException e) { 
    // TODO: handle error 
} 

आप जावा 6 या नीचे पर अटक कर रहे हैं ...

यह पैटर्न अशक्त के साथ आसपास mucking टाल: यह जानकर कि पास से निपटने के लिए पर एक अधिक विस्तार के लिए

try { 
     InputStream in = new FileInputStream(file); 
     try { 
      // TODO: work 
     } finally { 
      in.close(); 
     } 
    } catch (IOException e) { 
     // TODO: error handling 
    } 

, इस ब्लॉग पोस्ट पढ़ें: Java: how not to make a mess of stream handling। इसमें अधिक नमूना कोड, अधिक गहराई है और पकड़ ब्लॉक में लपेटने के नुकसान को कवर करता है।

25

कुछ ऐसा करने के लिए आपको यह करना चाहिए कि आप स्ट्रीम को बंद करने के प्रयास में IOException को फेंक दें या निगल लें।

FileInputStream fis = null; 
try 
{ 
    fis = new FileInputStream(file); 

    ... process ... 


} 
catch (IOException e) 
{ 
    ... blah blah blah ... 
} 
finally 
{ 
    try 
    { 
     if (fis != null) 
      fis.close(); 
    } 
    catch (IOException e) 
    { 
    } 
} 
4

तुम भी एक साधारण स्थिर सहायक विधि इस्तेमाल कर सकते हैं:

public static void closeQuietly(InputStream s) { 
    if (null == s) { 
     return; 
    } 
    try { 
     s.close(); 
    } catch (IOException ioe) { 
     //ignore exception 
    } 
} 

और से अपने अंत में ब्लॉक इस का उपयोग करें।

+0

ठीक है, यह एक NullPointerException को आमंत्रित करने जैसा दिखता है ... –

+0

टिप्पणी के लिए धन्यवाद, तदनुसार इसे बदल दिया – squiddle

0

उम्मीद है कि हम कुछ दिनों में जावा में बंद हो जाएंगे, और फिर हम बहुत सारी वर्बोजिटी खो देंगे।

तो इसके बजाय जावा में कहीं भी एक सहायक विधि होगी जिसे आप आयात कर सकते हैं, यह शायद "क्लोजेबल" इंटरफ़ेस और एक ब्लॉक भी लेगा। कि सहायक विधि कोशिश {closable.close()} पकड़ (IOException पूर्व) के अंदर {// blah} एक बार और सभी के लिए परिभाषित किया गया है, और फिर आप लिखने के लिए

Inputstream s = ....; 
withClosable(s) { 
    //your code here 
} 
3

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

तो चलो squiddle जवाब हो जाता है:

public static void closeQuietly(InputStream s) { 
    try { 
     s.close(); 
    } catch (IOException ignored) { 
    } 
} 
-4

आप FindBugs से या कोड है कि काम करता है होने के साथ एक साफ रिपोर्ट हो रही के साथ मुख्य रूप से चिंतित हैं? ये जरूरी नहीं है कि वही बात हो। आपका मूल कोड ठीक है (हालांकि मैं अनावश्यक if (fis != null) से छुटकारा पाउंगा क्योंकि OutOfMemoryException अन्यथा फेंक दिया गया होगा)। FileInputStream में एक फ़ाइनोलाइज़र विधि है जो आपके प्रसंस्करण में वास्तव में IOException प्राप्त करने की संभावना में आपके लिए स्ट्रीम बंद कर देगी। यह बस के लायक अपने कोड अधिक

  1. के अत्यंत संभावना नहीं परिदृश्य आप एक IOException हो और
  2. इस इतनी बार है कि आप finalizer बैकलॉग मुद्दों में चलाने के लिए शुरू होता है से बचने के लिए परिष्कृत बनाने का परेशान नहीं है।

संपादित करें: अगर आप इतने सारे IOExceptions कि आप finalizer कतार के साथ समस्याओं तो आप अब तक अब तक बड़ा मछली भून करने के लिए है में चल रहे हैं हो रही है! यह परिप्रेक्ष्य की भावना प्राप्त करने के बारे में है।

+2

अंतिम रूपकों पर निर्भर करना बहुत बुरा कदम है। फाइनलर केवल तभी बुलाया जाएगा जब स्ट्रीम ऑब्जेक्ट कचरा इकट्ठा किया जाता है, और ऐसा होने से पहले आपको फ़ाइल हैंडल से बाहर निकलने की संभावना है। * कभी भी कार्यक्षमता के लिए अंतिमकर्ताओं पर भरोसा न करें। मैं इतना तनाव नहीं कर सकता। – skaffman

+1

इस बात की कोई गारंटी नहीं है कि अंतिम रूपक अंतिम रूप से चलाया जाएगा या नहीं। – kpirkkal

+0

मुझे अंतिमकर्ताओं पर भरोसा करने के खतरों के बारे में पता है। मेरा मुद्दा यह था कि IOExceptions प्राप्त करना सामान्य प्रवाह नहीं है और इस असामान्य मामले के लिए शायद फ़ाइल डिस्क्रिप्टर को बंद करने पर भी लटका दिया जा सकता है। आपने FileInputStream पर कई IOExceptions को कब देखा था और क्या आपने इस सामान्य व्यवहार पर विचार किया था कि एक प्रोग्राम को निपटना चाहिए और चलना जारी रखना चाहिए? –

2

ज्यादातर मामलों में, मैं यह सिर्फ बेहतर नहीं है आईओ अपवाद को पकड़ने के लिए, और बस का उपयोग करने की कोशिश-अंत में:

final InputStream is = ... // (assuming some construction that can't return null) 
try { 
    // process is 
    ... 
} finally { 
    is.close(); 
} 

FileNotFoundException के अलावा, आप आम तौर पर नहीं "के आसपास काम" कर सकते हैं एक IOException। करने के लिए छोड़ दिया गया एकमात्र चीज एक त्रुटि की रिपोर्ट है, और आप आमतौर पर कॉल स्टैक को आगे बढ़ाएंगे, इसलिए मुझे अपवाद को प्रचारित करना बेहतर लगता है।

चूंकि IOException एक चेक अपवाद है, तो आपको यह कोड (और इसके किसी भी ग्राहक) throws IOException घोषित करना होगा। यह बहुत शोर हो सकता है, या हो सकता है कि आप IO का उपयोग करने के कार्यान्वयन विवरण को प्रकट नहीं करना चाहें। उस स्थिति में, आप पूरे ब्लॉक को एक अपवाद हैंडलर से लपेट सकते हैं जो को RuntimeException या एक सार अपवाद प्रकार में लपेटता है।

विवरण: मुझे पता है कि इसके बाद के संस्करण कोड try ब्लॉक से किसी भी अपवाद निगल जब finally ब्लॉक में close आपरेशन एक IOException का उत्पादन कर रहा हूँ। मुझे नहीं लगता कि यह एक बड़ी समस्या है: आम तौर पर, try ब्लॉक का अपवाद एक ही IOException होगा जो close विफल होने का कारण बनता है (यानी आईओ के लिए यह ठीक है और ठीक होने के बिंदु पर विफल रहता है) । यदि यह एक चिंता है, तो यह करीब "चुप्पी" करने में परेशानी के लायक हो सकता है।

+0

इनपुट स्ट्रीम के मामले में अज्ञात होने के बिंदु पर यह दुर्लभ है। 'FilterInputStream.' से प्राप्त किसी भी स्ट्रीम पर होने वाली अंतर्निहित' फ्लश() 'के कारण एक आउटपुट स्ट्रीम 'क्लोज़()' पर असफल हो सकती है। – EJP

1

बंद होने से पहले संभावित अपवाद छिपाने के बिना बंद होने में विफलता निम्न समाधान सही ढंग से फेंकता है।

try { 
    InputStream in = new FileInputStream(file); 
    try { 
     // work 
     in.close(); 
    } finally { 
     Closeables.closeQuietly(in); 
    } 
} catch(IOException exc) { 
    // kernel panic 
} 

यह काम करता है क्योंकि दूसरी बार has no effect को कॉल करना बंद कर देता है।

यह अमरूद Closeables पर निर्भर करता है, लेकिन squiddle द्वारा दिखाए गए अनुसार कोई भी अपना स्वयं का करीबी विधि लिख सकता है (serg10 भी देखें)।

सामान्य मामले में, एक करीबी त्रुटि की रिपोर्ट करना महत्वपूर्ण है क्योंकि बंद स्ट्रीम में कुछ अंतिम बाइट्स लिख सकता है, उदाहरण के लिए बफरिंग के कारण। इसलिए, आपका उपयोगकर्ता यह जानना चाहता है कि यह विफल रहा है, या आप शायद किसी भी तरह से कार्य करना चाहते हैं। अनुमोदित, यह FileInputStream के विशिष्ट मामले में सत्य नहीं हो सकता है, मुझे नहीं पता (लेकिन पहले से बताए गए कारणों से मुझे लगता है कि अगर यह किसी भी तरह से होता है तो एक करीबी त्रुटि की रिपोर्ट करना बेहतर होता है)।

उपरोक्त कोड एम्बेडेड प्रयास ब्लॉक की संरचना के कारण समझना थोड़ा मुश्किल है। इसे दो विधियों के साथ स्पष्ट माना जा सकता है, जो एक IOException फेंकता है और जो इसे पकड़ता है। कम से कम यही वह है जिसे मैं चुनूंगा।

private void work() throws IOException { 
    InputStream in = new FileInputStream(file); 
    try { 
     // work 
     in.close(); 
    } finally { 
     Closeables.closeQuietly(in); 
    } 
} 

public void workAndDealWithException() { 
    try { 
     work(); 
    } catch(IOException exc) { 
     // kernel panic 
    } 
} 

http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html (मैकडॉवेल द्वारा संदर्भित) के आधार पर।

10

आप try-with-resources सुविधा जेडीके 7 जोड़ सकते हैं। यह ठीक बनाया गया था बातें

static String readFirstLineFromFile(String path) throws IOException { 
    try (BufferedReader br = new BufferedReader(new FileReader(path))) { 
    return br.readLine(); 
    } 
} 

इस तरह का documenation कहते हैं से निपटने के लिए:

कोशिश के साथ-संसाधनों बयान सुनिश्चित करता है कि प्रत्येक संसाधन बयान के अंत में बंद कर दिया है।

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