I have csv with data like this:
1;57840
2;57840
3;57834
...
And simple scala code to read this data into Seq of Tuple2[Int,Int]
Code:
case class Tick(Data : Tuple2[Int,Int]) {
val tNum : Int = Data._1
val tVal : Int = Data._2
}
case class TicksDs(Data : Seq[Tick]) {
def size : Int = Data.size
}
class scvReader(CsvPath : String){
def using[A <: { def close(): Unit }, TicksDs](param: A)(f: A => TicksDs): TicksDs =
try {
f(param)
} finally {
//param.close()
}
def readTicks : TicksDs = {
using(io.Source.fromFile(CsvPath)) { source =>
TicksDs(source.getLines.map{oneLine => (oneLine.split(";")(0).toInt-1,
oneLine.split(";")(1).toInt)}.toSeq.map(x => Tick(x._1,x._2)))
}
}
}
object CurryingFuncs extends App {
val ticks : TicksDs = new scvReader("data/simple.csv").readTicks
println("ticks.size="+ticks.size+" ticks(Class): "+ticks.getClass.getName)
for (tick <- ticks.Data) {
println(tick.tNum+" "+tick.tVal+" "+tick.getClass.getName)
}
}
It's everything fine and this return me output:
ticks.size=50 ticks(Class): TicksDs
0 57840 Tick
1 57840 Tick
2 57834 Tick
3 57831 Tick
...
But when I uncomment line //param.close() it raise error
Exception in thread "main" java.io.IOException: Stream Closed
at java.io.FileInputStream.readBytes(Native Method)
...
...
Where is mistake and how fix it? Thanks.
Fix (thanks to jwvh):
...
def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
try f(param)
finally param.close()
...
...
using(io.Source.fromFile(CsvPath)) { source =>
TicksDs(source.getLines.map{oneLine => (oneLine.split(";")(0).toInt-1,
oneLine.split(";")(1).toInt)}.toList.map(x => Tick(x._1,x._2))) //was .toSeq now .toList
}
The error comes from the fact that you're closing the source before it is emptied.
This, source.getLines
, produces an Iterator[String]
which is evaluated lazily, and the toSeq
later that same line doesn't change it. If you use toList
instead then that will force evaluation of the complete file contents before the close()
.
Also, you don't need TicksDs
as a type parameter to using()
. It's not serving any purpose.
def using[A <: {def close(): Unit}]( . . .