2017-09-21 1 views
0

Im folgenden Code lese ich Nr. von Zeilen aus einer Datei. Wenn etwas schief geht, schließe ich den Dateizeiger. Aber wie kann ich herausfinden, ob f gültigen Zeiger enthält oder nicht?Schließen von Dateizeiger in Scala in Endlich

def countLines(filename:String):Option[Int] = { 
    try{ 
     val f = Source.fromFile(filename) 
     println(s"no. of lines ${f.getLines().size}") 
     Some(f.getLines.size) 
    } catch { 
     case ex: FileNotFoundException => { 
      println(s"file ${filename} not found") 
      None 
     } 
    } finally { 
     //f might not be a valid pointer depending on when the error occured 
    } 
} 

Das Buch lese ich bin verwendet var Zustand zu halten (wenn f gültig ist oder nicht), aber ich versuche, es zu benutzen nur unveränderliche Variablen aus Gründen zu vermeiden.

def countLines(filename:String):Option[Int] = { 

     var f:Option[Source] = None 
     try{ 
      f = Some(Source.fromFile(filename)) 
      println(s"no. of lines ${f.get.getLines().size}") 
      Some(f.get.getLines.size) 
     } catch { 
      case ex: FileNotFoundException => { 
       println(s"file ${filename} not found") 
       None 
      } 
     } finally { 
      for(i<-f){ 
       println("closing file") 
       i.close() 
      } 
     } 
    } 
+0

Gibt es irgendeinen Grund, dass Sie versuchen müssen, einen Versuch/catch/finally blockiert, anstatt ein Try-Objekt? oder wäre letzteres akzeptabel? –

Antwort

0

Ein Doppel Try(). Dies schließt die Ressource io, selbst wenn die getLines() fehlschlägt, aber nur, wenn die fromFile() erfolgreich ist.

import scala.util.Try 

def countLines(filename: String): Option[Int] = 
    Try(io.Source.fromFile(filename)).fold(_ => None, {f => 
    val count = Try(f.getLines().length) 
    f.close() 
    count.toOption 
    }) 
+0

yep, in meiner Lösung definitiv 'falten' Teil vermisst – tkachuko

0

Was denken Sie darüber? Wenn Sie Scala-Wege wollen - ich denke, dass es für Ihre Aufgabe gutes Beispiel ist:

def countLines(filename: String): Try[Int] = Try(Source.fromFile(filename).getLines.toList.size) 

    def test() = { 
     val filename = "/etc/passwd" 
     countLines(filename) match { 
        case Success(n) => println(n) 
        case Failure(f) => println(f) 
       } 
     } 

Wenn n - eine Zahl unserer Linien ist, und f - ein Throwable ist.

+0

Gefällt mir. Das andere Problem mit dem Original ist, dass im finally Block, f ist nicht einmal im Bereich – ConorR

+0

Es schließt Stream nicht im Falle 'getLines' Methode fehlschlagen – tkachuko

+0

Sind Sie sicher? Weil ich nicht bin - wenn wir Source.fromFile sehen - finden wir: () => inputStream.close(). Deshalb schließen Sie den Stream, falls die getLines-Methode fehlschlägt. – aarexer

0

Wie wäre es damit:

def countLines(filename: String): Option[Int] = { 
    val file = Try(Source.fromFile(filename)) 
    val count = file.map(_.getLines().size) 
    (for { 
    _ <- count.recoverWith { case _ => file.map(_.close()) } 
    lineCount <- count 
    } yield lineCount).toOption 
} 

des Lassen Sie analysieren:

  • Wenn die Datei nicht existiert wir Try Instanz versagt haben wird und Methode gibt None. In diesem Fall müssen Sie keine Ressourcen löschen, da kein tatsächlicher Stream erstellt wurde.
  • Wenn getLines aus irgendeinem Grund oder irgendetwas anderes während der Verarbeitung fehl geht nach Süden werden wir erstellt Strom in erster Linie für das Verständnis schließen

Hoffe, dass es

+0

@jwvh Sie können immer noch Karte auf sie anrufen – nevets1219

0

hilft einfach, wie über dieses:

def numLines(fileName:String):Option[Int] = { 
    try { 
    val f = scala.io.Source.fromFile(fileName) 
    try { Some(f.getLines.size) } 
    catch { case ex: IOException => 
     Console.err.println("i/o excetion") 
     None 
    } 
    finally { f.close() } 
    } 
    catch { 
    case ex: FileNotFoundException => 
     Console.err.println("file not found") 
     None 
    } 
} 
Verwandte Themen