Gibt es eine gute "scala-esque" (ich meine ich meine funktionale) Möglichkeit, Dateien in einem Verzeichnis rekursiv aufzulisten? Was ist mit einem bestimmten Muster?
Zum Beispiel rekursiv alle entsprechenden Dateien "a*.foo"
in c:\temp
.
Scala-Code verwendet normalerweise Java-Klassen für den Umgang mit E / A, einschließlich des Lesens von Verzeichnissen. Sie müssen also Folgendes tun:
import java.io.File
def recursiveListFiles(f: File): Array[File] = {
val these = f.listFiles
these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles)
}
Sie können alle Dateien sammeln und dann mit einem regulären Ausdruck filtern:
myBigFileArray.filter(f => """.*\.html$""".r.findFirstIn(f.getName).isDefined)
Oder Sie können den regulären Ausdruck in die rekursive Suche einbeziehen:
import scala.util.matching.Regex
def recursiveListFiles(f: File, r: Regex): Array[File] = {
val these = f.listFiles
val good = these.filter(f => r.findFirstIn(f.getName).isDefined)
good ++ these.filter(_.isDirectory).flatMap(recursiveListFiles(_,r))
}
listFiles
zurück,null
wennf
nicht auf ein Verzeichnis verwiesen wird oder wenn ein E / A-Fehler vorliegt (zumindest gemäß der Java-Spezifikation). Das Hinzufügen einer Nullprüfung ist wahrscheinlich für die Verwendung in der Produktion sinnvoll.f.isDirectory
wahr zurückzukehren , aberf.listFiles
zurückzukehrennull
. Wenn Sie beispielsweise keine Berechtigung zum Lesen der Dateien haben, erhalten Sie einenull
. Anstatt beide Prüfungen durchzuführen, würde ich nur die eine Nullprüfung hinzufügen.f.listFiles
null null zurückgegeben wird!f.isDirectory
.Ich würde eine Lösung mit Streams bevorzugen, da Sie über ein unendliches Dateisystem iterieren können (Streams sind faul bewertete Sammlungen).
Beispiel für die Suche
quelle
def getFileTree(f: File): Stream[File] = f #:: Option(f.listFiles()).toStream.flatten.flatMap(getFileTree)
Ab Java 1.7 sollten Sie alle java.nio verwenden. Es bietet nahezu native Leistung (java.io ist sehr langsam) und verfügt über einige nützliche Helfer
Java 1.8 bietet jedoch genau das, wonach Sie suchen:
Sie haben auch nach Dateivergleich gefragt. Versuchen Sie
java.nio.file.Files.find
und auchjava.nio.file.Files.newDirectoryStream
Siehe Dokumentation hier: http://docs.oracle.com/javase/tutorial/essential/io/walk.html
quelle
http://langref.org/scala+java/files
quelle
Scala ist eine Multi-Paradigmen-Sprache. Eine gute "scala-artige" Art, ein Verzeichnis zu iterieren, wäre die Wiederverwendung eines vorhandenen Codes!
Ich würde Commons-io als eine perfekt skala-artige Methode zum Iterieren eines Verzeichnisses betrachten. Sie können einige implizite Konvertierungen verwenden, um dies zu vereinfachen. Mögen
quelle
Ich mag Yuras Stream-Lösung, aber sie (und die anderen) rekursiv in versteckte Verzeichnisse. Wir können auch vereinfachen, indem wir die Tatsache nutzen, dass
listFiles
für ein Nicht-Verzeichnis null zurückgegeben wird.Jetzt können wir Dateien auflisten
oder realisieren Sie den gesamten Stream für die spätere Verarbeitung
quelle
Die FileUtils von Apache Commons Io passen in eine Zeile und sind gut lesbar:
quelle
Bisher hat noch niemand https://github.com/pathikrit/better-files erwähnt
quelle
Schauen Sie sich scala.tools.nsc.io an
Dort gibt es einige sehr nützliche Dienstprogramme, einschließlich Deep Listing-Funktionen für die Directory-Klasse.
Wenn ich mich richtig erinnere, wurde dies von retronym hervorgehoben (möglicherweise beigesteuert) und als Notlösung angesehen, bevor io eine neue und vollständigere Implementierung in der Standardbibliothek erhält.
quelle
Und hier ist eine Mischung der Stream-Lösung von @DuncanMcGregor mit dem Filter von @ Rick-777:
Auf diese Weise erhalten Sie einen Stream [Datei] anstelle einer (möglicherweise großen und sehr langsamen) Liste [Datei], während Sie entscheiden können, in welche Arten von Verzeichnissen Sie mit der Funktion descCheck () zurückkehren möchten.
quelle
Wie wäre es mit
quelle
Scala hat die Bibliothek 'scala.reflect.io', die als experimentell angesehen wurde, aber die Arbeit erledigt
quelle
Ich persönlich mag die Eleganz und Einfachheit der von @Rex Kerr vorgeschlagenen Lösung. Aber so könnte eine rekursive Schwanzversion aussehen:
quelle
Hier ist eine ähnliche Lösung wie bei Rex Kerr, jedoch mit einem Dateifilter:
Die Methode gibt eine Liste [Datei] zurück, was etwas praktischer ist als Array [Datei]. Außerdem werden alle Verstecke ignoriert, die ausgeblendet sind (dh mit '.' Beginnen).
Es wird teilweise mithilfe eines Dateifilters Ihrer Wahl angewendet, zum Beispiel:
quelle
Die einfachste Nur-Scala-Lösung (wenn es Ihnen nichts ausmacht, die Scala-Compiler-Bibliothek zu benötigen):
Ansonsten ist die Lösung von @ Renaud kurz und bündig (wenn es Ihnen nichts ausmacht, Apache Commons FileUtils einzubringen):
Wo
dir
ist eine java.io.File:quelle
Es scheint, dass niemand die
scala-io
Bibliothek von Scala-Inkubator erwähnt ...Oder mit
implicit
Oder wenn Sie
implicit
explizit wollen ...Die Dokumentation finden Sie hier: http://jesseeichar.github.io/scala-io-doc/0.4.3/index.html#!/file/glob_based_path_sets
quelle
Diese Beschwörung funktioniert bei mir:
quelle
Sie können die Schwanzrekursion dafür verwenden:
quelle
Warum verwenden Sie Javas Datei anstelle von Scalas AbstractFile?
Mit Scala's AbstractFile ermöglicht die Iterator-Unterstützung das Schreiben einer präziseren Version von James Moores Lösung:
quelle