gpt4 book ai didi

scala - 遍历文件的行

转载 作者:行者123 更新时间:2023-12-04 10:10:02 25 4
gpt4 key购买 nike

我想编写一个简单的函数来遍历文本文件的行。我相信 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 .这是可以理解的——第二个 lines在理解中最终为每一行打开(而不是关闭)一个文件
在第一。

就我而言,我知道 "file1.txt"很大,我不想把它吸进去
内存,但是第二个文件很小,所以我可以写一个不同的 linesEager像这样:
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)
}

这有效,但显然很难看。有人可以推荐统一和干净的吗
达到上述目的的方法。似乎您需要一种迭代器的方法
返回者 linesclose文件到达末尾时,以及
这一定发生在 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)

最佳答案

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)
}

但除非你指望 file2.txt 的内容在循环时更改 file1.txt ,最好将其读入 List在循环之前。无需将其转换为 Iterator .

关于scala - 遍历文件的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10338408/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com