I have 2 questions about the Scala class BufferedSource
.
How can I query the current reading position ?
I tried it with pos
:
object testapp extends App {
val doc = scala.io.Source.fromFile("text.txt")
println(doc.pos)
doc.next()
println(doc.pos)
doc.next()
println(doc.pos)
}
Output:
0
2049
2050
Why it jumps from 0 to 2049 ?!
Is there another way to query the position and/or set it somewhere else ?
Thanks for your help :-)
pos
returns position of last character returned by next()
, but the trick is that position is a combination of row and column encoded by position's encoder (scala.io.Position
) as a single Integer
:
The object Position provides convenience methods to encode * line and column number in one single integer. The encoded line * (column) numbers range from 0 to
LINE_MASK
(COLUMN_MASK
), * where0
indicates that the line (column) is undefined and *1
represents the first line (column)...https://github.com/scala/scala/blob/v2.11.8/src/library/scala/io/Position.scala
http://www.scala-lang.org/api/2.11.8/#scala.io.Source$RelaxedPosition$
Use Postioner
in order to get more readable info:
The current input and position, as well as the next character methods delegate to the positioner.
Example:
val doc = scala.io.Source.fromFile("aaa.txt")
val positioner = new doc.Positioner()
val positioned = doc.withPositioning(positioner)
positioned.next()
scala> positioner.cline -> positioner.ccol
res15: (Int, Int) = (1,2)
positioned.next()
scala> positioner.cline -> positioner.ccol
res17: (Int, Int) = (1,3)
P.S. Source
is intended for reading data as stream of characters, so it provides you conveniences like getLines()
etc, so basically that's why Positioner
works with rows and columns instead of an absolute position.
If you need an Iterator
that returns you an absolute position of every character, use zipWithIndex
:
scala> val doc = scala.io.Source.fromFile("aaa.txt").zipWithIndex
doc: Iterator[(Char, Int)] = non-empty iterator
scala> doc.next()
res38: (Char, Int) = (a,0)
scala> doc.next()
res39: (Char, Int) = (a,1)
scala> doc.next()
res40: (Char, Int) = (a,2)
scala> doc.next()
res41: (Char, Int) = (a,3)
scala> doc.next()
res42: (Char, Int) =
(
,4)