2015-06-22 2 views
2

У меня есть программа, которая должна читать файлы. Мне нужно проверять каждые 10 секунд, если есть новые файлы.Проверить наличие новых файлов в цикле - java

Чтобы сделать это, я сделал это:

ArrayList<File>oldFiles = new ArrayList<File>(); 
ArrayList<File>files=new ArrayList<File>(); 
while(isFinished != true){ 
     files=listFilesForFolder(folder); 
     if(oldFiles.size() != files.size()){ 
      System.out.println("Here is when a new file(s) is(are) in the folder"); 
     } 
     Thread.sleep(10000); 
} 

В принципе, listFilesForFolder получает назначение папки и проверить файлы там.

Моя проблема: Моя программа выполняет каждый цикл моей функции чтения для каждого файла. Я хочу сделать свою функцию чтения ТОЛЬКО на новые файлы.

Как я могу сделать что-то вроде:

новых файлов - старые файлов = моих файлов, которые я хочу прочитать.

+3

Не ответ, но обратите внимание, что проверка является неправильным. Если файл был удален и новый файл был создан в течение 10 секунд, вы не обнаружите новый файл, поскольку вы проверяете размер списков, а не контент. – giorashc

+0

Не могли бы вы переместить обработанные файлы в отдельную папку? Чем фактическая папка будет либо пустой (ничего не делать), либо содержать новые файлы. – slartidan

+0

Отключить тему, но посмотрите эту идиому на поток sleep: 'TimeUnit.SECONDS.sleep (10)' http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/TimeUnit.html – djeikyb

ответ

1

Вместо того, чтобы сравнивать старые и новые файлы, почему бы не написать метод, чтобы просто вернуть Last Modified Files.

public static ArrayList<File> listLastModifiedFiles(File folder, 
     long sleepDuration) throws Exception { 

    ArrayList<File> newFileList = new ArrayList<File>(); 

    for (File fileEntry : folder.listFiles()) 
     if ((System.currentTimeMillis() - fileEntry.lastModified()) <= sleepDuration) 
      newFileList.add(fileEntry); 

    return newFileList; 
} 

// Пример использования:

long sleepDuration = 10000; 
ArrayList<File> newFileList; 
int counter = 10; 

while (counter-- > 0) { 
    newFileList = listLastModifiedFiles(folder, sleepDuration); 

    for (File File : newFileList) 
     System.out.println(File.getName()); 

    Thread.sleep(sleepDuration); 
} 
+0

Это делает работу! Спасибо ! – tmylamoule

+0

Хорошо, ребята, мне нужна помощь еще раз. Я хочу остановить свою петлю в другом классе. Я попытался установить boolean isOver вместо счетчика -> 10. И активировать его с помощью сеттера, но это не работает. :/ – tmylamoule

+0

Было бы полезно, если вы зададите новый вопрос с соответствующим исходным кодом. Это даст больше понимания. – Rajesh

0

Предполагая, что вам нужно только, чтобы обнаружить новые файлы, а не модифицированные из них, и ни один файл не будет удален, а ваш код работает: ArrayList реализует removeAll(Collection c), который делает именно то, что вы хотите:

Удаляет из этого списка все его элементы, которые содержатся в указанной коллекции .

2

Вместо вашего подхода, почему бы не сохранить DateTime в последний раз, когда вы отметили.

Затем сравните этот раз к значению File.lastModified

Проблема с appraoch в том, что размеры массива будет отличаться даже в файле удаляется, и будет то же самое, если один файл удаляется и один файл добавлено.

1

Вы можете использовать sets. Вместо того, чтобы возвращать ArrayList, вы можете вернуть набор.

newFiles.removeAll(oldFiles); 

затем предоставит вам все файлы, которые не находятся в старом наборе. Я не говорю, что работа с датой модификации, о которой указывает Scary Wombat, является худшей идеей, я просто предлагаю другое решение.

Кроме того, вы должны изменить свой oldFiles, чтобы сохранить все файлы, с которыми вы уже столкнулись. Следующий пример, я думаю, делает то, что вы пытаетесь достичь.

private static Set<File> findFilesIn(File directory) { 
    // Or whatever logic you have for finding files 
    return new HashSet<File>(Arrays.asList(directory.listFiles())); 
} 

public static void main(String[] args) throws Throwable { 
    Set<File> allFiles = new HashSet<File>(); // Renamed from oldFiles 
    Set<File> newFiles = new HashSet<File>(); 

    File dir = new File("/tmp/stackoverflow/"); 
    while (true) { 
     allFiles.addAll(newFiles); // Add files from last round to collection of all files 

     newFiles = findFilesIn(dir); 
     newFiles.removeAll(allFiles); // Remove all the ones we already know. 

     System.out.println(String.format("Found %d new files: %s", newFiles.size(), newFiles)); 
     System.out.println("Sleeping..."); 
     Thread.sleep(5000); 
    } 
} 

Наборы более хранение данных наших правил для вашего случая, так как вам не нужен какой-либо порядок в вашей коллекции файлов и можете извлечь выгоду из более быстрого времени просмотра (при использовании HashSet).

+0

ArrayList уже реализует этот метод, см. Ссылку в моем ответе –

+0

Да, я прочитал ваш ответ и подумал об этом, но время поиска в ArrayList будет худшим случаем O (n), в то время как 'HashSet' имеет O (1). Если OP имеет дело со многими файлами, это может стать важным. – wonderb0lt

+0

Да, мне приходится иметь дело со многими «маленькими» файлами (например, 5Mb) Спасибо за весь ответ! Я работаю над этим ! – tmylamoule

0

Вы можете рассмотреть вопрос об использовании API Java WatchService, который использует операционную систему низкого уровня, чтобы уведомить вас об изменениях в файловой системе. Это более эффективно и быстрее, чем перечисление файлов в каталоге.

Существует учебник по Watching a Directory for Changes и API документирован здесь: Interface WatchService