Reputation: 45
Here is the code:
val bufferedSource = Source.fromFile("build.sbt")
val lines = bufferedSource.getLines()
bufferedSource.close()
ptintln(lines.next())
build.sbt file has such content:
name := "timeSeriesMerge"
version := "0.1"
scalaVersion := "2.11.8"
While debugging program in lines
I get such string with second character missing:
"nme := "timeSeriesMerge""
Can anybody explain how is this possible? It misses the second character in the string. Where is the problem? It misses the second character for first line only.
It also would be cool if somebody could explain why this code throws:
java.io.IOException: Stream Closed
Upvotes: 0
Views: 2766
Reputation: 14227
For your question 1, short answer: use Source.fromFile("build.sbt").getLines()
directly without using bufferedSource
, because bufferedSource
and lines
sharing same InputStream
, in debug time, maybe the index has changed by toString
Full Explanation:
This is caused by toString method has changed the Stream
's index that shared between lines
and bufferedSource
in the debug time , As we know when IDE stop in the breakpoint, it will invoke
variable
toString
methods. like for lines
and bufferedSource
variables, it will invoke Iterator.toString
, output like:
override def toString = (if (hasNext) "non-empty" else "empty")+" iterator"
> bufferedSource: non-empty iterator
> lines: non-empty iterator
As the above toString
method, it will invoke hasNext
firstly, this means it will invoke iter.hasNext in BufferedSource
, but there is a problem for BufferedSource.iter
:
override lazy val iter = (
Iterator
continually (codec wrap charReader.read())
takeWhile (_ != -1)
map (_.toChar)
)
when check hasNext
it will read a character from InputStream
. but this InputStream
is sharing with BufferedLineIterator
.
for val lines = bufferedSource.getLines()
is creating new BufferedLineIterator
from the BufferedSource
by BufferedSource.decachedReader with sharing same InputStream
between BufferedSource
.
So if we have invoked hasNext
method on BufferedSource
, it will change the index on BufferedLineIterator
.
Below is an example to demonstrate this:
//file content: import Settings._
val bufferedSource: BufferedSource = Source.fromFile("build.sbt")
val lines = bufferedSource.getLines()
bufferedSource.hasNext
val str = lines.next()
println(str)
> mport Settings._
As the above example, we manually invoke hasNext
method, so the Stream
index has changed to next.
And for when we using IDE to debug, it invokes toString
randomly, so it maybe cause the second character missing by debug in:
https://github.com/scala/scala/blob/2.13.x/src/library/scala/io/BufferedSource.scala#L55
Upvotes: 4
Reputation: 530
Here, You are calling "next" on Iterator after the stream has been closed.
You should close the stream only after you have done using it. Therefore, the correct sequence of statements should be
println(lines.next())
bufferedSource.close()
Also, if you want to iterate over the complete file, you need to call next inside a loop. You can try -
for(line <- lines){
println(line)
}
Upvotes: 2