Share via


vb.net Return The Newest (latest) File Date and Time In Directory?

Question

Tuesday, December 11, 2012 2:47 AM | 1 vote

I found this code,  works great.  but want to change it to display just the date and time not full path and file name.

Private Sub btn_check_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_check.Click
 
 Dim files() As String = System.IO.Directory.GetFiles("C:\Workarea")
        System.Array.Sort(files, New FileInfoComparer)

        MessageBox.Show("Latest file: " & files(files.Length - 1))
        MessageBox.Show("Oledest file: " & files(0))

End Sub


Public Class FileInfoComparer
        Implements IComparer

        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare

            Dim firstFile As New System.IO.FileInfo(x.ToString)
            Dim secondFile As New System.IO.FileInfo(y.ToString)

            Return DateTime.Compare(firstFile.LastWriteTime, secondFile.LastWriteTime)

        End Function

I want to stay away from any next or loop as the directory I am reading has thousands of files

any help is greatly appreciated. 

All replies (15)

Tuesday, December 11, 2012 3:27 PM ✅Answered | 1 vote

        Dim fi As New System.IO.DirectoryInfo("C:\WorkFolder")
        Dim files = fi.GetFiles.ToList
        Dim first = (From file In files Select file Order By file.CreationTime Ascending).FirstOrDefault
        Dim last = (From file In files Select file Order By file.CreationTime Descending).FirstOrDefault
 

Success
Cor


Tuesday, December 11, 2012 7:49 PM ✅Answered

Any solution you come up with will involve iterating through every file in the directory.  You can mitigate this somewhat by using the EnumerateFiles method (available starting with .Net 4.0).  This method will begin to return results before all the files have been returned, rather than waiting for all files.  Either way, though, since you want the oldest and newest, you will have to iterate over all the files.  It's best to do this only once and keep track of the oldest and newest ones.

Here is some code that uses it.  It searched a directory tree of about 47000 files in about 4 seconds.

    Sub Main()

        Dim sw As New Stopwatch()

        Dim folderToSearch As String = "folder name here"
        Dim oldestFile As FileInfo = Nothing
        Dim newestFile As FileInfo = Nothing

        Dim fileCount As Integer = 0

        Dim folder As New DirectoryInfo(folderToSearch)

        Console.Clear()
        Console.WriteLine("Searching {0}", folderToSearch)
        Console.WriteLine()

        sw.Start()

        For Each finfo In folder.EnumerateFiles("*", IO.SearchOption.AllDirectories)
            If oldestFile Is Nothing OrElse finfo.LastWriteTime <= oldestFile.LastWriteTime Then
                oldestFile = finfo
            End If

            If newestFile Is Nothing OrElse finfo.LastWriteTime >= newestFile.LastWriteTime Then
                newestFile = finfo
            End If

            fileCount += 1
        Next

        sw.Stop()

        Console.WriteLine("Oldest file is {0} {1}.", oldestFile.LastWriteTime, oldestFile.Name)
        Console.WriteLine("Newest file is {0} {1}.", newestFile.LastWriteTime, newestFile.Name)

        Console.WriteLine()
        Console.WriteLine("{0} files searched.  Elapsed time: {1}", fileCount, sw.Elapsed.ToString("mm\:ss\.fff"))

        Console.WriteLine()
        Console.WriteLine("Press ENTER to exit...")
        Console.ReadLine()
    End Sub

YMMV


Tuesday, December 11, 2012 3:00 AM

How about replacing you two MessageBox statements with

Dim lastDate As DateTime = New IO.FileInfo(files(files.Length - 1).LastWriteTime
MessageBox.Show("Newest file Date: " & lastDate.ToString())

Dim firstDate As DateTime = New IO.FileInfo(files(0).LastWriteTime
MessageBox.Show("Oldest file Date: " & firstDate.ToString())

Tuesday, December 11, 2012 7:07 AM

try this 

Dim directory = New DirectoryInfo("C:\MyDirectory")
Dim myFile = (From f In directory.GetFiles() Order By f.LastWriteTime Descending f).First().CreationTime

good luck

Please mark the post as an answer that helps/solves your problem.


Tuesday, December 11, 2012 7:09 AM

In addition to Blackwood,

Or using Linq that I comparer is a little bit a homework question (it is done like was done with punch cards).

        Dim fi As New System.IO.DirectoryInfo("C:\Workfolder")
        Dim files = fi.GetFileSystemInfos.ToList
        Dim first = (From file In files Select file Order By file.CreationTime Ascending).FirstOrDefault
        Dim last = (From file In files Select file Order By file.CreationTime Descending).FirstOrDefault

Success
Cor


Tuesday, December 11, 2012 2:18 PM

Thanks Cor,   is there a way to look at files only and omit subdirectories? 


Tuesday, December 11, 2012 4:07 PM

Cor, I guess I need to re-think this.  my original code and your code takes too long to return as the archive folder has thousands of files.   thoughts? 

 Dim fi As New System.IO.DirectoryInfo("C:\Workarea\Archive")        Dim files = fi.GetFileSystemInfos.ToList        Dim first = (From file In files Select file Order By file.CreationTime Ascending).FirstOrDefault        ' Dim last = (From file In files Select file Order By file.CreationTime Descending).FirstOrDefault        TxtBx1.Text = first.LastWriteTime

Tuesday, December 11, 2012 4:09 PM

If it takes long than is it your file access not the Linq part. 

You can do nothing to go around that beside buying a faster storage device.

Success
Cor


Tuesday, December 11, 2012 4:53 PM

How about using timers and storing your file information as long as the archive directory doesn't change in length?

Imports System.IO

Public Class Form1

    Dim first As Object
    Dim Counter As Integer = 0
    Dim FileInformation As String

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Timer1.Interval = 1
        Timer2.Interval = 1
        Timer1.Start()
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        RichTextBox1.Text = FileInformation
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        If Directory.GetFiles("C:\Users\John\Desktop\Test Folder").Length <> Counter Then
            Timer2.Start()
            Counter = Directory.GetFiles("C:\Users\John\Desktop\Test Folder").Length
        End If
    End Sub

    Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
        Dim fi As New System.IO.DirectoryInfo("C:\Users\John\Desktop\Test Folder")
        Dim files = fi.GetFileSystemInfos.ToList
        first = (From file In files Select file Order By file.CreationTime Ascending).FirstOrDefault
        FileInformation = first.LastWriteTime
        Timer2.Stop()
    End Sub

You've taught me everything I know but not everything you know.


Tuesday, December 11, 2012 5:14 PM | 1 vote

How about using timers and storing your file information as long as the archive directory doesn't change in length?

Imports System.IO

Public Class Form1

    Dim first As Object
    Dim Counter As Integer = 0
    Dim FileInformation As String

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Timer1.Interval = 1
        Timer2.Interval = 1
        Timer1.Start()
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        RichTextBox1.Text = FileInformation
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        If Directory.GetFiles("C:\Users\John\Desktop\Test Folder").Length <> Counter Then
            Timer2.Start()
            Counter = Directory.GetFiles("C:\Users\John\Desktop\Test Folder").Length
        End If
    End Sub

    Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
        Dim fi As New System.IO.DirectoryInfo("C:\Users\John\Desktop\Test Folder")
        Dim files = fi.GetFileSystemInfos.ToList
        first = (From file In files Select file Order By file.CreationTime Ascending).FirstOrDefault
        FileInformation = first.LastWriteTime
        Timer2.Stop()
    End Sub

You've taught me everything I know but not everything you know.

Mr, Monkeyboy,

That is not sorting, but maybe he simply wants the filewatcher 

http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx

Only his question was about the Icomparer a synonym for sort so quite confusing as this is market as answer for those searching for this question.

Success
Cor


Tuesday, December 11, 2012 7:14 PM

This has a problem in that you are calling Directory.GetFiles twice which will perform the disk I/O twice!


Thursday, December 13, 2012 5:38 PM

Thank you,  Chris Dunaway much faster!!!


Thursday, December 20, 2012 4:53 PM

Chris,  I have another question on this topic.  I am needing to change my folder to search to an FTP folder for security reasons.   here is the code

Dim folderToSearch As String = ("ftp://username:userpassword@servername/foldername") 

            Dim oldestFile As FileInfo = Nothing
            Dim newestFile As FileInfo = Nothing

            Dim fileCount As Integer = 0

            Dim folder As New DirectoryInfo(folderToSearch)

            For Each finfo In folder.EnumerateFiles("*", IO.SearchOption.AllDirectories)

                 If oldestFile Is Nothing OrElse finfo.LastWriteTime <= oldestFile.LastWriteTime Then
                   oldestFile = finfo
                 End If

                If newestFile Is Nothing OrElse finfo.LastWriteTime >= newestFile.LastWriteTime Then
                    newestFile = finfo
                End If

                fileCount += 1
            Next
            txtbx_folderactivity.Text &= ("Searching: " & folderToSearch) & vbNewLine
            txtbx_folderactivity.Text &= ("Oldest file: " & oldestFile.LastWriteTime) & vbNewLine
            txtbx_folderactivity.Text &= ("Newest file: " & newestFile.LastWriteTime) & vbNewLine
            TxtBx_INAsn.Text = newestFile.LastWriteTime

        End If

I can open a new thread to get someone elses help.  


Friday, December 21, 2012 7:25 PM

I'm not sure if the EnumerateFiles method supports a path like that.  You may need to map the ftp site to a drive letter in Windows.  Once done, I think it should work.  See this link for information.  I have no experience in this.

http://www.windowsitpro.com/article/ftp/how-can-i-map-to-an-ftp-server-as-a-drive-

Or you can use software such as WebDrive:  (http://www.webdrive.com/products/webdrive/index.html) or ExpanDrive (http://www.expandrive.com/).  Both of these are not free, but have trials so you can at least see if they will help you.  There may be free alternatives, but I don't know them.


Saturday, December 22, 2012 3:36 PM

Thanks Chris!