如何从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
答案 0 :(得分:2)
最简单的方法是在迭代器上使用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$2.next(Iterator.scala:39)
at scala.collection.Iterator$$anon$2.next(Iterator.scala:37)
at scala.collection.LinearSeqLike$$anon$1.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
}
最后,封装更好的版本:
{{1}}