来自文件的可重用流

Reusable streams from file

如何在 Scala 中从文件创建可重用流?我有一个很大的文件,我想多次使用它的内容,但是我可能不需要完整地读取整个文件

我试过类似的方法,但没有成功,

  // file iterator
  val f =  Source.fromFile("numberSeq.txt").getLines

  // construct stream from file iterator
  def numSeq: Stream[BigInt] = Stream.cons(BigInt(f.next()),numSeq)

  //test
  numSeq take 5 foreach println
  numSeq take 5 foreach println //the stream continues to print next file lines instead of going back to the first line

最简单的方法是在迭代器上使用 toStream

scala> val f = List(1,2,3,4,5,6,7,8,9,10).toIterator.toStream
f: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> f take 5 foreach println
1
2
3
4
5

scala> f take 5 foreach println
1
2
3
4
5

在您的具体案例中,问题是您在每次 numSeq 调用时都有全新的流,因为使用 def 而不是 val。你仍然需要def进行递归定义,但不要忘记在使用前将其保存到val

scala> def numSeq: Stream[BigInt] = Stream.cons(BigInt(f.next()),numSeq)
numSeq: Stream[BigInt]

scala> val numSeq1 = numSeq
numSeq1: Stream[BigInt] = Stream(1, ?)

scala> numSeq1 take 5 foreach println
1
2
3
4
5

scala> numSeq1 take 5 foreach println
1
2
3
4
5

错误用法示例(注意numSeq而不是numSeq1):

scala> numSeq take 5 foreach println
6
7
8
9
10

scala> numSeq take 5 foreach println
java.util.NoSuchElementException: next on empty iterator
  at scala.collection.Iterator$$anon.next(Iterator.scala:39)
  at scala.collection.Iterator$$anon.next(Iterator.scala:37)
  at scala.collection.LinearSeqLike$$anon.next(LinearSeqLike.scala:59)
  at .numSeq(<console>:14)
  ... 33 elided

顺便说一句,cons 有更可爱的 #:: 语法:

import Stream._
def numSeq: Stream[BigInt] = BigInt(f.next()) #:: numSeq
val numSeq1 = numSeq

最后是封装性更好的版本:

val numSeq = { 
  def numSeq: Stream[BigInt] = BigInt(f.next()) #:: numSeq 
  numSeq
}