Scala 在文件的行上迭代

Scala 在文件的行上迭代,scala,io,iterator,Scala,Io,Iterator,我想写一个简单的函数,它遍历文本文件的行。我相信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(ne

我想写一个简单的函数,它遍历文本文件的行。我相信
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 ( l1 <- lines("file1.txt"); l2 <- lines("file2.txt") ){ 
    do_stuff(l1, l2) 
}
然后将我的理解转化为:

for (l1 <- lines("file1.txt"); l2 <- linesEager("file2.txt")){ 
    do_stuff(l1, l2) 
}
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)
rjhala@goto:$scalac WordsFail.scala
rjhala@goto:$scala失败密码字
地狱世界
java.io.FileNotFoundException:passwd(打开的文件太多)
在java.io.FileInputStream.open(本机方法)
位于java.io.FileInputStream。(FileInputStream.java:120)
位于scala.io.Source$.fromFile(Source.scala:91)
位于scala.io.Source$.fromFile(Source.scala:76)
失败时$行(WordsFail.scala:8)
失败时$$anonfun$main$1.apply(WordsFail.scala:18)
失败时$$anonfun$main$1.apply(WordsFail.scala:17)
位于scala.collection.Iterator$class.foreach(Iterator.scala:652)
位于scala.io.BufferedSource$BufferedLineIterator.foreach(BufferedSource.scala:30)
失败时$.main(WordsFail.scala:17)
at Fail.main(WordsFail.scala)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)中
位于java.lang.reflect.Method.invoke(Method.java:597)
在scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply处(ScalaClassLoader.scala:78)
位于scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:24)
位于scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:88)
位于scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:78)
位于scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
位于scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:33)
位于scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:40)
位于scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:56)
在scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:80)中
位于scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89)
位于scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

也许你应该看看scala手臂(https://github.com/jsuereth/scala-arm)并让文件(文件输入流)在后台自动关闭。

提供了一种很好的机制,可以在使用完资源后自动关闭资源

import resource._
import scala.io.Source

for (file1 <- managed(Source.fromFile("file1.txt"));
     l1 <- file1.getLines();
     file2 <- managed(Source.fromFile("file2.txt"));
     l2 <- file2.getLines()) {
  do_stuff(l1, l2)
}
导入资源_
导入scala.io.Source

对于(file1 Code one在REPL(Scala 2.9)中为我工作)。不幸的是,它不是。@userunknown它可以工作,但不能扩展。(想象大文件/许多行。)你错了,2.8也没有关闭任何东西,这可以很容易地通过在示例程序上运行lsof来验证(或者通过查看源代码更费劲)。如果你对
2.9
有问题,而你对
2.8
没有问题,那么这些问题一定来自其他地方。将其转换为列表不会导致整个文件保存在内存中吗?我希望避免这种情况……但是
file2.txt
很小,因此应该可以接受。另外,这就是你的
lineseger
所做的(
.toList
),除了你在内存中创建它,然后在
file1.txt
中的每一行都扔掉它。嗨,戴夫,是的,你是对的。我误解了理解中的不同动作必须有相同的类型,所以当
toList
时,无关的
toliterator
就足够了……谢谢!@RanjitJhala-只有当您从表单中生成一个值以供理解时,类型才需要兼容。不一定相同,但兼容。
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)
import resource._
import scala.io.Source

for (file1 <- managed(Source.fromFile("file1.txt"));
     l1 <- file1.getLines();
     file2 <- managed(Source.fromFile("file2.txt"));
     l2 <- file2.getLines()) {
  do_stuff(l1, l2)
}