2012-01-14 12 views
20

क्या संसाधनों को ठीक से जारी करने का एक बेहतर तरीका है - निम्नलिखित कोड लिखने का एक बेहतर तरीका?स्कैला अंत में बंद/फ़्लशिंग संसाधन को बंद कर देता है

 val out: Option[FileOutputStream] = try { 
      Option(new FileOutputStream(path)) 
     } catch { 
      case _ => None 
     } 


     if (out.isDefined) { 

      try { 
      Iterator.continually(in.read).takeWhile(-1 != _).foreach(out.get.write) 
      } catch { 
      case e => println(e.getMessage) 
      } finally { 
      in.close 
      out.get.flush() 
      out.get.close() 
      } 

     } 
+0

(बस tryclose._ और tryclose.JavaImplicits._ आयात करने के लिए सुनिश्चित करें) पहले व्यक्ति सफलतापूर्वक तत्काल, मैं अंततः एक पैटर्न पर मारा जो मेरे लिए बहुत उपयोगी रहा है। मैंने इसे समान स्टैक ओवरफ्लो प्रश्न पर एक उत्तर के रूप में लिखा: http://stackoverflow.com/a/34277491/501113 – chaotic3quilibrium

उत्तर

18

कुछ इस तरह एक अच्छा विचार है, लेकिन मैं इसे एक विधि बनाने चाहते हैं:

def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Option[B] = { 
    try { 
    val r = resource 
    try { Some(code(r)) } 
    finally { cleanup(r) } 
    } catch { 
    case e: Exception => None 
    } 
} 

(ध्यान दें कि हम केवल एक बार पकड़ने, तुम वास्तव में संदेश एक मामले और नहीं में मुद्रित करना चाहते हैं दूसरा, तो आपको दोनों की तरह पकड़ना होगा)।

cleanly(new FileOutputStream(path))(_.close){ fos => 
    Iterator.continually(in.read).takeWhile(_ != -1).foreach(fos.write) 
} 

चूंकि यह एक मान देता है, तो आप एक मिल जाएगा: विधि इतनी तरह प्रयोग किया जाता है, (, पकड़ने Error भी आम तौर पर मूर्ख है, क्योंकि यह से उबरने के लिए लगभग असंभव है यह भी ध्यान रखें कि मैं केवल अपवाद को पकड़ने के।) Some(()) यदि यह यहां सफल हुआ (जिसे आप अनदेखा कर सकते हैं)।


संपादित करें: यह अधिक सामान्य बनाना, मैं वास्तव में यह एक Either बजाय लौट होगा, ताकि आप अपवाद मिलता है। इसलिए जैसा:

def cleanly[A,B](resource: => A)(cleanup: A => Unit)(code: A => B): Either[Exception,B] = { 
    try { 
    val r = resource 
    try { Right(code(r)) } finally { cleanup(r) } 
    } 
    catch { case e: Exception => Left(e) } 
} 

अब अगर आप एक Right मिलता है, सब ठीक हो गया। यदि आपको Left मिलता है, तो आप अपना अपवाद चुन सकते हैं। यदि आपको अपवाद की परवाह नहीं है, तो आप इसे .right.toOption का उपयोग किसी विकल्प में मैप करने के लिए कर सकते हैं, या केवल .right.map का उपयोग कर सकते हैं या जो भी सही परिणाम पर संचालित हो, केवल तभी होता है (जैसे Option)। (पैटर्न मिलान Either एस से निपटने का एक उपयोगी तरीका है।)

+0

आप संसाधन को क्यों निर्दिष्ट करते हैं? इसका उपयोग क्यों न करें। क्या आप इस सरलीकरण के साथ कुछ भी गलत देखते हैं, एक कोशिश को हटाते हैं। 'साफ परिभाषित करें [ए <: java.io.बंद करने योग्य, बी] (संसाधन: ए) (कोड: ए => बी): या तो [अपवाद, बी] = { कोशिश करें { दाएं (कोड (संसाधन)) } पकड़ें { केस ई: अपवाद => बाएं (ई) } अंत में { resource.close } } ' – rvange

+3

@rvange - संसाधन उत्पन्न करने से अपवाद हो सकता है, इसलिए आप नाम से कॉल करना चाहते हैं। संसाधन 'java.io.Closeable' नहीं हो सकता है, इसलिए उपयोगकर्ता द्वारा निर्दिष्ट क्लीनअप को अनुमति देने के लिए यह अधिक सामान्य है। यदि आपके पास केवल 'java.io.Closeable' है और आप या तो निश्चित हैं कि संसाधन अपवाद के बिना स्वयं को बनाएगा, या आप उस अपवाद को प्रचारित करना चाहते हैं, तो आपका कोड ठीक है। –

17

Scala-ARM

इस परियोजना स्केला पुस्तकालय में स्वचालित-संसाधन-प्रबंधन के लिए स्काला इनक्यूबेटर परियोजना बनना है पर एक नज़र ...

... स्काला एआरएम है पुस्तकालय उपयोगकर्ताओं को "प्रबंधित" विधि का उपयोग कर कोड के ब्लॉक के भीतर संसाधनों को खोलने की अनुमति देता है। "प्रबंधित" विधि अनिवार्य रूप से "ऐसी किसी भी चीज का तर्क लेती है जिसमें एक करीबी या निपटान विधि है" और एक नया प्रबंधित संसाधन स्रोत बनाता है।

+0

क्या आपको स्कैला-एआरएम की स्थिति पता है? यह काफी मृत दिखता है - मई से कोई काम नहीं करता है। –

0

वैकल्पिक रूप से आप इसे चॉपी के आलसी TryClose monad के साथ कर सकते हैं।

val output = for { 
    fin <- TryClose(in) 
    fout <- TryClose.wrapWithCloser(new FileOutputStream(path))(out => {out.flush(); out.close();}) 
} yield wrap(Iterator.continually(fin.read).takeWhile(-1 != _).foreach(fout.get.write)) 

// Then execute it like this: 
output.resolve 

अधिक यहाँ जानकारी: https://github.com/choppythelumberjack/tryclose

क्योंकि मैं, घोंसला कई java.lang.AutoCloseable उदाहरणों करने में सक्षम होने की जरूरत है, जिनमें से प्रत्येक पर निर्भर करता है

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