scala – 迭代文件的行
发布时间:2020-12-16 19:21:16 所属栏目:安全 来源:网络整理
导读:我想写一个简单的函数,迭代文本文件的行.我相信2.8可以做到: def lines(filename: String) : Iterator[String] = { scala.io.Source.fromFile(filename).getLines} 就是这样,但在2.9中,上面的方法不起作用,而是我必须这样做: def lines(filename: String)
我想写一个简单的函数,迭代文本文件的行.我相信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 comprehension中组合上面的迭代器: for ( l1 <- lines("file1.txt"); l2 <- lines("file2.txt") ){ do_stuff(l1,l2) } 这再次,曾经与2.8一起正常工作但导致“太多打开的文件” 在我的情况下,我知道“file1.txt”很大,我不想把它吸进去 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 (l1 <- lines("file1.txt"); l2 <- linesEager("file2.txt")){ do_stuff(l1,l2) } 这有效,但显然很难看.有人可以建议制服和清洁 谢谢! 顺便说一句 – 这是显示问题的完整程序的最小版本: 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=%sn".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) 解决方法
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) } 但是,除非你在循环访问file1.txt时指望改变file2.txt的内容,否则最好在循环之前将其读入List.没有必要将其转换为迭代器. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |