Search code examples
vb.netauto-incrementwinscp-net

Increment filename-number by the amount of files in directory .Net


My program finds and lists all files located on a remote folder. The same program is able to save new files created into the same folder. I can decide the filename, but I need the program to give some sort of "ID" to each of them. I would like the program to be able to Count the number of files in the folder at all times, and name the file being saved as the next number in line.

See, I have 10 files in the folder. And I go in to create a new one using the New_Case Event. I write in a bunch of information and in the end hit Save_Case event. I want the program to name the file "Somename11"

And then, since its now 11 files in the folder I do the same and create a New Case - Bunch of information - and Save, and the next file will be called "Someothername12".

I have yet to find any examples that works, but I found many where the number increases if the filename already exists in the folder. I need the Number to increase regardless.

I have tried using a Counter that increments each time, but since this program will be used by multiple users at the same time, I need to avoid two users incrementing the same digit.

So by incrementing it by the number of files in the folder would work much better I believe.

If it helps to nail this down, I am unable to use

My.Computer.FileSystem.GetFiles

as it's remote, and that only wanna search my PC.

I am using WinSCP .NET to have an SFTP to the Server.


Solution

  • This isn't the most efficient thing in the world, but it's a simple way to accomplish your stated goal:

    Public Function SaveWithUniqueFileName(desiredFilePath As String, contents() As Byte) As String
        Dim uniqueFilePath As String = Nothing
        Dim suceeded As Boolean = False
        For i As Integer = 1 To Integer.MaxValue
            If i = 1 Then
                uniqueFilePath = desiredFilePath
            Else
                Dim uniqueFileName As String = Path.GetFileNameWithoutExtension(desiredFilePath) & i.ToString() & Path.GetExtension(desiredFilePath)
                uniqueFilePath = Path.Combine(Path.GetDirectoryName(desiredFilePath), uniqueFileName)
            End If
            If Not File.Exists(uniqueFilePath) Then
                Try
                    Using stream As New FileStream(uniqueFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None)
                        stream.Write(contents, 0, contents.Length)
                    End Using
                    suceeded = True
                    Exit For
                Catch ex As IOException
                End Try
            End If
        Next
        If Not suceeded Then
            uniqueFilePath = Nothing
        End If
        Return uniqueFilePath
    End Function
    

    That method will save to the desired file name if it doesn't already exist, or append a unique number to the file name if one does already exist. For instance, if you you call it like this:

     Dim data() As Byte = {72, 101, 108, 108, 111}
     Dim savedToPath As String = SaveWithUniqueFileName("C:\Test.txt", data)
     If savedToPath IsNot Nothing Then
         Console.WriteLine("Successfully saved to " & savedToPath)
     Else
         Console.WriteLine("Failed to save")
     End If
    

    There are many improvements to be made. It ought to have some cap on how high it counts and it should handle the exception better than just eating it and returning null (ideally the consuming code would know why it failed). Also, it loops through all the same-named files starting at 1, so the more files there are with the same name, the slower it would go. If performance is an issue, you could have some way to sync all the clients so that they don't all try to save at the same time. That could be as simple as locking a single flag file in the same folder, or it could be as involved as a client/server arrangement where all clients send requests to a single server which handles the saving in an orderly serial fashion. Either way, this simple example is a good place to start.