2015-04-05 106 views
1

如何从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 

回答

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 

在你的具体情况下,问题是,你对代替val因为defnumSeq呼叫全新的流。你仍然需要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 

最后,VERSI在更好的封装上:

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

感谢您的解释! – Rnet 2015-04-05 17:09:20