Фильтр GetFiles() по нескольким критериям

Не был уверен, как сформулировать название моего вопроса. но надеюсь это будет быстро.

У меня есть куча файлов PDF в папке, я хочу получить дату последнего изменения или создания файла определенного типа. Мой код работает, но он дает мне результаты всех файлов PDF. Мне нужны только результаты определенных имен.

Например. в моем «c:\temp\» у меня есть несколько файлов PDF, которые начинаются примерно с тех же трех первых букв, за которыми следуют цифры или несколько букв.

Имена файлов, такие как tes8796, fes8897895, bas232. и т.д. и т.п. Я хочу видеть только результаты файлов "fes" и "bas", я не хочу видеть файлы "tes"...

Любые идеи?

Я считаю, что это должно выглядеть примерно так {"fes*.pdf", "Bas*.pdf"})

Мой код работает (я хочу получить результат только для файлов "fes" и "bas").

Dim pathx As String = "C:\temp\"
Dim directory = New DirectoryInfo(pathx)
Dim from_date As DateTime = DateTime.Now.AddHours(-24)
Dim to_date As DateTime = DateTime.Now
Dim files = directory.GetFiles().Where(Function(file) file.LastWriteTime >= from_date AndAlso file.LastWriteTime <= to_date)
For Each filx In files
    ListBox1.Items.Add(filx)
Next

person TuckingFypo    schedule 14.12.2014    source источник


Ответы (3)


Есть несколько способов сделать это. Во-первых, вы можете применить фильтр PDF в начале: directory.GetFiles("*.pdf"), а затем просто расширить условия вашей функции:

Dim names() As String = {"fes", "bas"}

Dim files = di.GetFiles("*.pdf").Where(
        Function(file) (file.LastWriteTime >= from_date _ 
               AndAlso file.LastWriteTime <= DateTime.Now) _
                  AndAlso (names.Contains(file.Name.ToLowerInvariant.Substring(0, 3)))
            )

For Each filx In files
    Console.WriteLine(filx)
Next

Проблема в том, что это зависит от того, что начальные имена файлов всегда и навсегда будут состоять из 3 символов. Кроме того, посмотрите на свой код: как только вы получите свой массив, вы прокручиваете его, чтобы отправить его в ListBox. Обычно крутые ребята используют LINQ, чтобы избежать циклов. Итак, чтобы исправить обе проблемы:

ListBox1.Items.AddRange(di.GetFiles("*.pdf").Where(
        Function(f) (f.LastWriteTime >= from_date AndAlso f.LastWriteTime <= DateTime.Now) _
            AndAlso names.Any(Function(n) f.Name.ToLowerInvariant.StartsWith(n))
            ).ToArray)

Я избавился от имен переменных, которые уже существуют в NET в виде типов, таких как Directory и File. Вторая функция фильтрует массив имен, затем результаты передаются напрямую в коллекцию элементов списка.

Почти во всех случаях простой цикл будет быстрее:

Dim myfiles = directory.GetFiles("*.pdf")
For Each f In myfiles
    If f.LastAccessTime >= from_date AndAlso f.LastWriteTime <= DateTime.Now Then
        For Each s As String In names
            If f.Name.ToLowerInvariant.StartsWith(s.ToLowerInvariant) Then
                Console.WriteLine(f)
                Exit For                     ' abort when found
            End If
        Next
    End If
Next
  • вероятно, более понятно для самопровозглашенного новичка в VB.NET
  • это можно постепенно отлаживать
  • обработка выполняется от 2 до 100 раз быстрее (в зависимости от количества файлов и фильтров имен)a
  • будет работать с различными фильтрами имен файлов
  • объединяет операцию поиска/фильтрации с публикацией, чтобы исключить дополнительный цикл (Console.WriteLine может добавлять к элементам или добавлять в список по мере необходимости).

aЗначение разницы во времени имеет значение, зависит от того, как она используется и от нагрузки. Если он работает непрерывно для обработки большого количества файлов, это может иметь значение. Как часть настольного приложения, скорее всего, нет.

person Ňɏssa Pøngjǣrdenlarp    schedule 15.12.2014

Вызываемый вами метод GetFiles перегружен и позволяет вам указать единственный шаблон для сопоставления. Вы можете вызвать этот метод дважды (один раз для каждого шаблона), а затем объединить результаты, или же вы можете получить все файлы с помощью одного вызова, как и вы, а затем добавить другое условие к вашему Where вызову для фильтрации имени, а также даты/ время.

person jmcilhinney    schedule 15.12.2014
comment
Я так и думал, но я немного новичок, когда дело доходит до VB. так что, может быть, вы можете ПОЖАЛУЙСТА отредактировать то, что у меня есть, чтобы получить результаты, которые я хочу? Кроме того, имен файлов будет больше, а не два. Спасибо - person TuckingFypo; 15.12.2014

Вы были очень близки. Я бы сделал что-то вроде этого:

    Dim pathx As String = "C:\temp\"
    Dim directory = New IO.DirectoryInfo(pathx)
    Dim from_date As DateTime = DateTime.Now.AddHours(-24)
    Dim to_date As DateTime = DateTime.Now
    Dim files = directory.GetFiles().Where(Function(file) file.LastWriteTime >= from_date AndAlso file.LastWriteTime <= to_date AndAlso file.Name.EndsWith(".pdf") AndAlso (file.Name.StartsWith("fes") OrElse file.Name.StartsWith("bas")))
    For Each filx In files
        ListBox1.Items.Add(filx)
    Next
person Joe Uhren    schedule 15.12.2014