I have the following code to decode a BitVector. How can I remove the exception and throw a failure?
def decode(b: BitVector) = {
if (!applies) {
Attempt.successful(DecodeResult.apply(null, b))
} else {
string.decode(b) match {
case Attempt.Successful(str) => {
val contentSize = str.value.slice(0, 2)
val content = str.value.slice(2, contentSize.hex2int() + contentSize.length)
if(!content.forall(_.isLetterOrDigit)){
throw new IllegalArgumentException()
}
val remain = str.value.slice(contentSize.hex2int() + contentSize.length, str.value.length)
Attempt.successful(DecodeResult.apply(content, BitVector(remain.getBytes)))
}
case Attempt.Failure(e) => Attempt.failure(e)
}
}
}
Related
I need to process list of entry in parallel and validate the results. Can anybody help me in achieving this in Scala
it is something like below,
FileList = List { "/temp/File1", "/temp/File2","/temp/File3","/temp/File4"........}
for( file <- FileList){
Future { getRecCount(file) } // Need to create a List with all Futures
}
Now i need to check the result of all Futures till it completes
getRecCount - will calculate the record count and writes into an file
If you're just interested in Exception, you can wrap the body of Future in Try and use Future.traverse as #adrice727 mentioned for paralles files processing:
// Sequence of files for processing
val files = Seq[String]("/tmp/1.txt", "/tmp/2.txt", "/tmp/3.txt", "/tmp/4.txt",
"/tmp/5.txt", "/tmp/6.txt")
def fileHandler(path: String): String = {
val idx = files.indexOf(path)
// Throw exception for each second file
if (idx % 2 == 0) throw new Exception(s"Unable to hande $path")
else path
}
val futures: Future[Seq[Try[String]]] = Future.traverse(files){ path =>
Future {
// Wrap it by Try
Try {
// Each file handler
fileHandler(path)
}
}
}
futures.map { seq =>
seq.map {
case Success(s) => println(s"Result: $s")
case Failure(ex) => println(s"Exception: ${ex.getMessage}")
}
}
Thanks - This is how i implemented
val tobeProcesssed : Seq[String] = Seq("FileName1", "FileName2", "FileName3,"FileName4) // Created a Seq with File Names
val latch = new CDL(tobeProcesssed.size)
val trackFutures: Future[Seq[Try[Boolean]]] = Future.traverse(tobeProcesssed.seq) { fileNm =>
Future {
LOG.info("In the Futures Loop for {}", fileNm)
Try {
doProcessing(fileNm)
}
}
}
trackFutures.map { seq =>
seq.map {
case Success(state) => {
if (state) {
LOG.info("On Sucess - {} - {}", latch.getCount, state)
return = 0
latch.countDown()
} else {
LOG.error("Failed - {} - {}", latch.getCount, state)
while (latch.getCount > 0) {
return = 1
latch.countDown()
}
}
}
case Failure(exception) => {
LOG.error("Versioning Failed -{} - {}", latch.countDown(), exception)
while (latch.getCount > 0) {
return = = 1
latch.countDown()
}
}
}
}
latch.await()
In the following code, I am reading no. of lines from a file. If something goes wrong, I'll like to close the file pointer. But how can I find out if f contains valid pointer or not?
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
}
}
The book I am reading uses var to maintain state (if f is valid or not) but I am trying to avoid it for sake of using only immutable variables.
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()
}
}
}
A double Try(). This closes the io resource even if the getLines() fails, but only if the fromFile() succeeds.
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
})
What do you think about this?
If you want Scala-way - i think it's good example for your task:
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)
}
}
When n - is a number of our lines, and f - is a Throwable.
How about this:
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
}
Let's analyze it:
If file does not exist we will have failed Try instance and method returns None. In this case you do not need to clear any resources as no actual stream was created.
If getLines fails for any reason or anything else during processing goes south we will close created stream in first line of for comprehension
Hope it helps
Simply, how about this:
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
}
}
I wrote the following piece of code
def info(): MyCaseClass = {
Try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
} match {
case Failure(f) => {
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
}
case Success(s) => s
}
}
Is there an even shorter way to deal with the fact that the file system operation could result in an exception so I handle it as above. Like can I not just somehow have to deal with failure case only. Like in case of Future exceptions, the future just does what it has to but for exceptions only we define recover and recoverWith. Something analogous is possible here?
Simply use try instead of Try:
def info(): MyCaseClass = {
try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
} catch {
case f: Throwable => {
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
}
}
}
Try has recover as well:
def info(): MyCaseClass = {
(Try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
} recover {
case f =>
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
}).get
}
.getOrElse seems to be what you are looking for:
def info(): MyCaseClass = {
Try {
val fileSys = new File("somePath")
MyCaseClass(fileSys.getTotalSpace, fileSys.getUsableSpace)
}.getOrElse({
logger.error(s"Could not read information:${f.getStackTrace}")
MyCaseClass(0, 0)
})
}
My code throw exception scala.util.control.BreakControl, but I don't know why. Does anyone know?
Some place I use breakable and break, but I don't why cause this exception.
fragment 1
breakable {
for (quaOfLine <- dataOfLine) {
try {
// ... some other code
if (judgeTime(jsonQua.getInt("startTime")) == judgeTime(jsonLine.getInt("startTime"))) {
// ... some other code
if (quaRRIDs.length / RRIDs.length.toFloat >= 0.8 || quaRRIDs.length / RRIDs.length.toFloat <= 1.2) {
var count = 0
breakable {
for (rrid <- RRIDs) {
for (quaRRID <- quaRRIDs) {
if (rrid == quaRRID) {
count += 1
break //break
}
}
}
}
if (count / RRIDs.length.toFloat >= 0.8) {
sameLine = qualifier + "::" + value
break // break
}
}
}
} catch {
case e: Throwable => e.printStackTrace
}
}
}
fragment 2
breakable {
for (quaOfDest <- dataOfDest) {
try {
val qualifier = quaOfDest.getString("qualifier")
val value = quaOfDest.getString("value")
val jsonQua = new JSONObject(value)
val (quaSLon, quaSLat, quaELon, quaELat) = getSELonLat(jsonQua)
if (jsonQua.getInt("timeBucket").toString == judgeTime(jsonLine.getInt("startTime"))) {
someDest = qualifier + "::" + value
break //break
}
} catch {
case e: Throwable => e.printStackTrace
}
}
}
scala.util.control.BreakControl is thrown by the method scala.util.control.Breaks.break. It is used for simulating the break statement from Java. It is used like this:
import scala.util.control.Breaks.{break, breakable}
breakable {
for(i <- 1 until 10) {
println(i)
if(i > 5) break
}
}
BreakControl is a private class so normally it won't be thrown by anything else than break.
This also means that inside a breakable block you shouldn't catch BreakControl yourself. You break inside a try block and then catch all Throwables and print them. BreakControl is a Throwable so it will be caught by you instead of by the breakable method.
If you really want to catch all Exceptions/Throwables, you should do something like this:
import scala.util.control.Breaks.{break, breakable}
import scala.util.control.ControlThrowable
breakable {
for(i <- 1 until 10) {
try {
println(i)
if(i > 5) break
} catch {
case c: ControlThrowable => throw c
case t: Throwable => t.printStackTrace
}
}
}
The Scala Standard Library also includes a special construct for cases like this which lets you catch all Throwables except for fatal ones like OutOfMemoryError or StackOverflowError, and also everything that extends ControlThrowable:
import scala.util.control.NonFatal
try {
//do stuff
} catch {
case NonFatal(e) => e.printStackTrace
}
I am trying to save a large data set (50MB) into file. But I get the following error:
java.lang.StackOverflowError
at scala.collection.Iterator$$anon$12.hasNext(Iterator.scala:350)
at scala.collection.Iterator$$anon$12.hasNext(Iterator.scala:350)
...
It looks to me like a recursion problem but I can't find where it would come from. Plase help. Function that makes the Iterator[String]:
override def toJsonIterator: Iterator[String] = {
val lastId = listMap.keys.toList.sorted.last
def evalJS(id: Int): String = {
Json.prettyPrint(listMap(id).toJsonValue) + (if(id != lastId) "," else "")
}
listMap.keys.toList.sorted
.foldLeft(Iterator("{"))( (sum, id) => sum ++ Iterator(evalJS(id)) ) ++ Iterator("}")
}
The save to file code:
private def write(st: Iterator[String], file: String): Unit = {
if (st.isEmpty) return ()
val f = new File(file)
if (!f.getParentFile().exists()) f.getParentFile().mkdirs()
if (!f.exists()) f.createNewFile()
val p = new java.io.PrintWriter(f)
try {
while(st.hasNext) {
p.println(st.next())
}
}
catch {
case e:Exception => println("Error: could not write to file \""+file+"\" because: "+e)
}
finally { p.close() }
}