Перебор строк файла

Я хотел бы написать простую функцию, которая перебирает строки текстового файла. Я считаю, что в 2.8можно было сделать:

def lines(filename: String) : Iterator[String] = { 
    scala.io.Source.fromFile(filename).getLines
}

и это было так, но в 2.9приведенное выше не работает, и вместо этого я должен сделать:

def lines(filename: String) : Iterator[String] = { 
    scala.io.Source.fromFile(new File(filename)).getLines()
}

Теперь проблема в том, что я хочу скомпоновать приведенные выше итераторы в forпонимание:

for ( l1 <- lines("file1.txt"); l2 <- lines("file2.txt") ){ 
    do_stuff(l1, l2) 
}

Это снова, используется нормально работает с 2.8, но вызывает "слишком много открытых файлов" исключение, которое будет выброшено в 2.9. Это понятно -- вторая строка в понимании заканчивается открытием (а не закрытием) файла для каждой строки во-первых.

В моем случае я знаю, что "file1.txt"большой, и я не хочу втягивать его в
памяти, но второй файл мал, поэтому я могу написать другой строк Eager вот так:

def linesEager(filename: String): Iterator[String] = 
    val buf = scala.io.Source.fromFile(new File(filename))
    val zs  = buf.getLines().toList.toIterator
    buf.close()
    zs

а затем превратить мое for-comprehension в:

for (l1 <- lines("file1.txt"); l2 <- linesEager("file2.txt")){ 
    do_stuff(l1, l2) 
}

Это работает, но явно уродливо. Может кто-нибудь предложить униформу и чистую способ достижения вышеперечисленного. Похоже, вам нужен способ для итератора возвращается строкв закрываетфайл, когда он достигает конца, и это должно было происходить в 2.8, поэтому там это сработало?

Спасибо!

Кстати, вот минимальная версия полной программы, показывающая проблему:

import java.io.PrintWriter
import java.io.File

object Fail { 

  def lines(filename: String) : Iterator[String] = { 
    val f = new File(filename)
    scala.io.Source.fromFile(f).getLines()
  }

  def main(args: Array[String]) = { 
    val smallFile = args(0)
    val bigFile   = args(1)

    println("helloworld")

    for ( w1 <- lines(bigFile)
        ; w2 <- lines(smallFile)
        ) 
    {
      if (w2 == w1){
        val msg = "%s=%s\n".format(w1, w2)
        println("found" + msg)
      }
    }

    println("goodbye")
  }

}

В 2.9.0я компилирую с помощью scalac WordsFail.scalaи затем получаю это:

rjhala@goto:$ scalac WordsFail.scala 
rjhala@goto:$ scala Fail passwd words
helloworld
java.io.FileNotFoundException: passwd (Too many open files)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:120)
    at scala.io.Source$.fromFile(Source.scala:91)
    at scala.io.Source$.fromFile(Source.scala:76)
    at Fail$.lines(WordsFail.scala:8)
    at Fail$$anonfun$main$1.apply(WordsFail.scala:18)
    at Fail$$anonfun$main$1.apply(WordsFail.scala:17)
    at scala.collection.Iterator$class.foreach(Iterator.scala:652)
    at scala.io.BufferedSource$BufferedLineIterator.foreach(BufferedSource.scala:30)
    at Fail$.main(WordsFail.scala:17)
    at Fail.main(WordsFail.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:78)
    at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88)
    at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78)
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33)
    at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
7
задан Ranjit Jhala 26 April 2012 в 23:48
поделиться