Рекурсивно ходить по БОЛЬШОМУ каталогу, используя продолжения Scala 2.8
Можно ли рекурсивно обходить каталог, используя продолжения Scala (введено в 2.8)?
Мой каталог содержит миллионы файлов, поэтому я не могу использовать Stream
потому что я получу нехватку памяти. Я пытаюсь написать Actor
отправить рабочим актерам параллельную обработку файлов.
У кого-нибудь есть пример?
3 ответа
Если вы хотите придерживаться Java 1.6 (в отличие от FileVistor
в 1.7), и у вас есть подкаталоги вместо всех ваших миллионов файлов в одном каталоге, вы можете
class DirectoryIterator(f: File) extends Iterator[File] {
private[this] val fs = Option(f.listFiles).getOrElse(Array[File]())
private[this] var i = -1
private[this] var recurse: DirectoryIterator = null
def hasNext = {
if (recurse != null && recurse.hasNext) true
else (i+1 < fs.length)
}
def next = {
if (recurse != null && recurse.hasNext) recurse.next
else if (i+1 >= fs.length) {
throw new java.util.NoSuchElementException("next on empty file iterator")
}
else {
i += 1;
if (fs(i).isDirectory) recurse = new DirectoryIterator(fs(i))
fs(i)
}
}
}
Это требует, чтобы ваша файловая система не имела петель. Если в нем есть циклы, вам нужно отслеживать каталоги, в которые вы попали, и избегать повторного их повторения. (Если вы даже не хотите наносить удары по файлам дважды, если они связаны из двух разных мест, вам придется поместить все в набор, и нет смысла использовать итератор вместо простого чтения всей информации о файле в объем памяти.)
Это больше вопрос, чем ответ.
Если ваш процесс связан с вводом / выводом, параллельная обработка может не сильно улучшить вашу пропускную способность. Во многих случаях это ухудшит состояние, вызвав трепетание головки диска. Прежде чем проделать большую работу в этом направлении, посмотрите, насколько занят диск. Если он уже большую часть времени занят одним потоком, то будет полезен максимум один поток, и даже это может привести к обратным результатам.