我想编写一个Scala脚本来递归处理目录中的所有文件。对于每个文件,我想看看是否有任何情况,其中字符串出现在第X行和第X - 2行。如果发生这种情况,我想停止处理该文件,并将该文件名添加到地图文件名对出现次数的影响。我今天刚刚开始学习Scala,我的文件递归代码正常工作,需要一些字符串搜索帮助,这是我到目前为止所做的:
import java.io.File
import scala.io.Source
val s1= "CmdNum = 506"
val s2 = "Data = [0000,]"
def processFile(f: File) {
val lines = scala.io.Source.fromFile(f).getLines.toArray
for (i = 0 to lines.length - 1) {
// want to do string searches here, see if line contains s1 and line two lines above also contains s1
//println(lines(i))
}
}
def recursiveListFiles(f: File): Array[File] = {
val these = f.listFiles
if (these != null) {
for (i = 0 to these.length - 1) {
if (these(i).isFile) {
processFile(these(i))
}
}
these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles)
}
else {
Array[File]()
}
}
println(recursiveListFiles(new File(args(0))))
答案 0 :(得分:7)
您可以这样做:
def processFile(f: File) {
val src = Source.fromFile(f)
val hit = src.getLines().sliding(3).exists{
case List(l0, l1, l2) => l0.contains(s1) && l2.contains(s1)
case _ => false
}
src.close
// do something depending on hit like adding to a Map
}
首先你不需要转换为数组,你可以保留迭代器只读取找到匹配所需的行。
您可以使用sliding
使用3行的滑动窗口来获取派生迭代器,您可以在其中查找i
行和i+2
上的字符串。
exists
测试此滑动迭代器的元素是否满足谓词。为方便起见,case
将模式匹配从滑动窗口元素的3行到3个val。 我必须使用REPL来找出滑动实际返回的类型。
最后不要忘记关闭src。
如果您需要事件计数:
val count = src.getLines().sliding(3).filter{
case List(l0, l1, l2) => l0.contains(s1) && l2.contains(s1)
case _ => false
}.size
您可以过滤事件,然后获取尺寸......
编辑了短于3行的文件的匹配错误
答案 1 :(得分:2)
这是另一种方法:
import java.io.File
import scala.io.Source
val s1= "CmdNum = 506"
def filesAt(f: File): Array[File] = if (f.isDirectory) f.listFiles flatMap filesAt else Array(f)
def filterFiles(arr: Array[File]) = arr filter (
Source
fromFile _
getLines ()
sliding 3
exists {
case List(l1, l2, l3) => List(l1, l3) forall (_ contains s1)
case _ => false
}
)
println(filterFiles(filesAt(new File(args(0)))))
虽然我承认我有点作弊。我实际上必须写这个而不是Source fromFile _
:
Source.fromFile(_)(scala.io.Codec.ISO8859)
因为否则,Scala会对无效的UTF-8编码进行禁止。
答案 2 :(得分:1)
它需要精炼来处理短于3行的文件,但是在第一次尝试时我会尝试这样的事情:
def checkFile(file: File) = {
val lines = ...
(lines zip lines.tail.tail) exists { _1 = _2 }
}
然后
val files = ...
val validFiles = files filter { checkFile }
道歉如此简短,我正在接听我的手机......