对于你的问题1,简短回答:直接使用Source.fromFile("build.sbt").getLines()而不使用bufferedSource,因为bufferedSource和lines共享相同的InputStream,在调试时,可能索引已更改toString
完整说明:
这是由于 toString 方法在 debug time 中改变了Stream 的索引在lines 和bufferedSource 之间共享,我们知道当 IDE 停在 breakpoint 时,它会 invoke variable toString 方法。对于lines 和bufferedSource 变量,它将调用Iterator.toString,输出如下:
override def toString = (if (hasNext) "non-empty" else "empty")+" iterator"
> bufferedSource: non-empty iterator
> lines: non-empty iterator
和上面的toString方法一样,它会先调用hasNext,也就是说它会在BufferedSource中调用iter.hasNext,但是BufferedSource.iter有问题:
override lazy val iter = (
Iterator
continually (codec wrap charReader.read())
takeWhile (_ != -1)
map (_.toChar)
)
当检查hasNext 时,它会从InputStream 读取一个字符。但是这个InputStream 正在与BufferedLineIterator 共享。
对于val lines = bufferedSource.getLines() 正在从BufferedSource 由BufferedSource.decachedReader 创建新的BufferedLineIterator,并共享相同的InputStream between BufferedSource。
所以如果我们在BufferedSource 上调用了hasNext 方法,它将改变BufferedLineIterator 上的索引。
下面是一个例子来证明这一点:
//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._
如上例,我们手动调用hasNext方法,所以Stream索引变成了next。
而当我们使用IDE进行调试时,它会随机调用toString,所以可能会导致第二个字符被debug in:
https://github.com/scala/scala/blob/2.13.x/src/library/scala/io/BufferedSource.scala#L55