Reputation: 33
I am reading a file that contain the following:
16,44,34
16,47,18
22,44,28
22,47,24
but I just want to read the first and the last line of the file, In this moment I am reading the file as an Iterator:
while (in2.hasNext) {
val s = in2.next(',').toInt
val p = in2.next(',').toInt
val o = in2.next('\n').toInt
}
but I am reading the whole file, exist a way in scala to do it?
Upvotes: 0
Views: 2454
Reputation: 40510
Well, you can write it a little nicer, and save on not having to parse every line in the file, but you will still have to read them all, unless you are willing to do some acrobatics with random access files and binary data (probably, not worth the effort, unless the file is truly huge).
val lines = Source.fromFile("input_file.csv").getLines
val firstLine = if(lines.hasNext) Some(lines.next) else None
val lastLine = lines.foldLeft(Option.empty[String]) { case (_, line) => Some(line) }
val spos: Seq[Seq[Int]] = (firstLine ++ lastLine).map(_.split(",").map(_.toInt))
// next line will fail if there are fewer than two lines in the file
// or if either first or last line doesn't have exactly three comma-separated fields
// I am just putting it here to illustrate how you could extract the parsed data
val Seq(Seq(s1, p1, o1), Seq(s2, p2, o2)) = spos
Update
Ok, if you really don't want to have to read through the entire file, you can try something like this (this is a crude approach, based on the fact that your lines are all short, so I can be sure that if I land somewhere ~1000 bytes from the end of the file, I'll definitely be well before the start of the last line.
val file = new RandomAccessFile("input_file.csv", "r")
val firstLine = Option(file.readLine)
if(file.length > 1024 + firstLine.fold(0)(_.length))
file.skipBytes(file.length - 1024)
val lastLine = Iterator.continually(file.readLine)
.takeWhile(_ != null)
.foldLeft(Option.empty[String]) { case (_, line) => line }
(the rest of the earlier snippet can stay the same).
Upvotes: 3