2016-08-09 1 views
1

Ich versuche, eine durch Komma getrennte Datei in scala zu lesen und diese in eine Liste von Json-Objekten umzuwandeln. Der Code funktioniert, wenn alle Datensätze gültig sind. Wie finde ich die Ausnahme für die Datensätze, die in meiner Funktion nicht gültig sind. Wenn ein Datensatz nicht gültig ist, sollte er die Datei auslösen und ausschließen und weiterlesen. Aber in meinem Fall, sobald ein ungültiger Datensatz kommt, stoppt die Anwendung.scala io Ausnahmebehandlung

def parseFile(file: String): List[JsObject] = { 

val bufferedSource = Source.fromFile(file) 
try { 
    bufferedSource.getLines().map(line => { 
    val cols = line.split(",").map(_.trim) 
    (Json.obj("Name" -> cols(0), "Media" -> cols(1), "Gender" -> cols(2), "Age" -> cols(3).toInt)) // Need to handle io exception here. 
    }).toList 
} 

finally { 
    bufferedSource.close() 
    } 
} 
+0

Was meinen Sie mit "eine Ausnahme auslösen und weiterlesen"? Wenn eine Ausnahme ausgelöst wird, können Sie nicht weitermachen ... – Alec

+1

Um eine Ausnahme auszulösen, brechen Sie die aktuelle Ausführung ab und geben den Aufruf-Stack zurück, bis Sie einen Handler für diese Ausnahme gefunden haben. Wenn Sie einen Fehler nur lokal behandeln möchten, sollten Sie niemals eine Ausnahme auslösen und sie nur mit lokalen Code-/Methodenaufrufen behandeln oder die Ausnahme lokal abfangen. –

+0

vielleicht sollten Sie nur einige Gültigkeitsprüfungen für eine Zeile durchführen (wie closes.size> = x) oder wie auch immer Sie die Gültigkeit sicherstellen wollen und die Zeile sonst überspringen oder in eine separate Liste setzen und zumindest ein Tupel mit dem "correct "Json und die falschen Zeilen. Auf diese Weise können Sie mit diesen Zeilen umgehen oder den Benutzer informieren. Eine andere Möglichkeit, Ihr Problem in Scala zu behandeln, ist das eine oder andere Objekt, das Sie zurückgeben können, und Ihren json darin einfügen oder andernfalls, wenn Fehler die fehlerhaften Linien auftreten. Sie sollten versuchen, Ausnahmen wegzulassen, wenn sie nicht wirklich benötigt werden, weil sie Nebenwirkungen sind. – sascha10000

Antwort

2

ich glaube, Sie verwenden Option profitieren können (http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html) und das Try-Objekt (http://danielwestheide.com/blog/2012/12/26/the-neophytes-guide-to-scala-part-6-error-handling-with-try.html)

Was Sie hier tun, alle Arbeiten zu stoppen, wenn ein Fehler (dh geschieht werfen Sie die Karte, um außerhalb) Eine bessere Möglichkeit besteht darin, den Fehler zu isolieren und ein Objekt zurückzugeben, das wir herausfiltern können. Nachfolgend finden Sie eine schnelle Umsetzung I

gemacht
package csv 

import play.api.libs.json.{JsObject, Json} 

import scala.io.Source 
import scala.util.Try 

object CsvParser extends App { 

    //Because a bad row can either != 4 columns or the age can not be a int we want to return an option that will be ignored by our caller 
    def toTuple(array : Array[String]): Option[(String, String, String, Int)] = { 
    array match { 
     //if our array has exactly 4 columns 
     case Array(name, media, gender, age) => Try((name, media, gender, age.toInt)).toOption 
     // any other array size will be ignored 
     case _ => None 
    } 
    } 

    def toJson(line: String): Option[JsObject] = { 
    val cols = line.split(",").map(_.trim) 
    toTuple(cols) match { 
     case Some((name: String, media: String, gender: String, age: Int)) => Some(Json.obj("Name" -> name, "Media" -> media, "Gender" -> gender, "Age" -> age)) 
     case _ => None 
    } 
    } 

    def parseFile(file: String): List[JsObject] = { 

    val bufferedSource = Source.fromFile(file) 
    try { bufferedSource.getLines().map(toJson).toList.flatten } finally { bufferedSource.close() } 

    } 

    parseFile("my/csv/file/path") 

} 

Der obige Code wird alle Zeilen ignorieren, wo es nicht genau 4 Spalten. Es enthält auch die NumberFormatException von .toInt.

Die Idee besteht darin, den Fehler zu isolieren und einen Typ zurückzugeben, mit dem der Aufrufer arbeiten kann, wenn die Zeile geparst wurde ... oder zu ignorieren, wenn ein Fehler aufgetreten ist.

+0

Hallo @Jono Vielen Dank für das Beispiel und eine sehr hilfreiche Referenz, das war genau ich suchte :) –

+0

Gern geschehen. Mir ist gerade aufgefallen, dass ich den Versuch-endlich verpasst habe. Es scheint einige gut bekannte Probleme mit Scala Source zu geben. Schau auf meinen editted Code zurück. Es scheint für mich zu funktionieren und stellt sicher, dass der InputStream der Source geschlossen ist – Jono