none
Creating Files based on Files name in a folder ? RRS feed

  • Question

  • Hello.

    My app creates files in a folder, with numerical-based file names (for e.g. txt files : 1.txt , 2.txt , ...)

    So if there are 3 files, the forth file's name should be 4 . It is quite simple:

    Directory.GetFiles(Application.StartupPath & "\_customers\", "*.cinfo").Count + 1

    But when it comes to deleting a file among other files in the same folder , there will be problem. If there are 5 files and the forth is deleted , files are : 1.txt, 2.txt, 3.txt, 5.txt . Now with the code above, app creates  new file with the name 5 (5 already exists). App should follow the numerical pattern in creating new files.How to do the trick ?

    Friday, March 2, 2018 10:26 PM

All replies

  • My app creates files in a folder, with numerical-based file names (for e.g. txt files : 1.txt , 2.txt , ...)

    So if there are 3 files, the forth file's name should be 4 . It is quite simple:

    But when it comes to deleting a file among other files in the same folder , there will be problem. If there are 5 files and the forth is deleted , files are : 1.txt, 2.txt, 3.txt, 5.txt . Now with the code above, app creates  new file with the name 5 (5 already exists). App should follow the numerical pattern in creating new files.

    Assuming you mean that you want a new file in this case to use 6.txt,
    it sounds like a rather rudimentary programming task.

    Get a list of all filenames in the directory.

    Identify the highest numerical filename in the list.

    Start the numbering for new files at one greater.

    - Wayne

    Friday, March 2, 2018 11:10 PM
  • Hello.

    My app creates files in a folder, with numerical-based file names (for e.g. txt files : 1.txt , 2.txt , ...)

    So if there are 3 files, the forth file's name should be 4 . It is quite simple:

    Directory.GetFiles(Application.StartupPath & "\_customers\", "*.cinfo").Count + 1

    But when it comes to deleting a file among other files in the same folder , there will be problem. If there are 5 files and the forth is deleted , files are : 1.txt, 2.txt, 3.txt, 5.txt . Now with the code above, app creates  new file with the name 5 (5 already exists). App should follow the numerical pattern in creating new files.How to do the trick ?

    Hi

    Here is a Function that will return the next number (string) for the sequence and optionally, return the first gap where eg a file(s) have been deleted. You would have your own path of course, and wouldn't need the test files I used in this excample.

    Option Strict On
    Option Explicit On
    Public Class Form1
      Dim path As String = "C:\Users\lesha\Desktop\Plans\New folder\NumberFiles"
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    	' add some test files
    	For i As Integer = 1 To 6
    	  Dim s As String = "Freddy" & i.ToString
    	  ' skip file 4 (as though deleted)
    	  If Not i = 4 Then
    		IO.File.WriteAllText(path & "\" & i.ToString & ".cinfo", s)
    	  End If
    	Next
    
    	Dim NextFile As String = path & "\" & FindGapOrHighest(True) & ".cinfo"
      End Sub
      Function FindGapOrHighest(Optional findgap As Boolean = False) As String
    	Dim files() As String = IO.Directory.GetFiles(path, "*.cinfo")
    	Dim j As Integer = 0
    	For Each file As String In files
    	  Dim n As Integer = CInt(IO.Path.GetFileNameWithoutExtension(file))
    	  If findgap AndAlso Not n = j + 1 Then
    		' found gap
    		Exit For
    	  Else
    		j += 1
    	  End If
    	Next
    	Return (j + 1).ToString
      End Function
    End Class


    Regards Les, Livingston, Scotland

    Saturday, March 3, 2018 12:00 AM
  • Here is another idea where if there is more than one missing we get that too.

    Imports System.IO
    
    Public Class Form3
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim intValues = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.txt").
                    ToList().
                    Select(Function(f)
                                Dim testInt As Integer = 0
                                if Integer.TryParse(Path.GetFileNameWithoutExtension(f) ,testInt) 
                                   Return testInt
                                Else 
                                   return nothing
                                End If                           
                           End Function).
                    ToList()
        
            Dim result = intValues.FindMissing()
            Console.WriteLine(String.Join(",", result))
            Console.WriteLine(result.OrderByDescending(Function(x) x).FirstOrDefault())
    
        End Sub
    End Class
    
    Public Module MyExtensions
        <Runtime.CompilerServices.Extension>
        Public Function FindMissing(ByVal list As List(Of Integer)) As IEnumerable(Of Integer)
            list.Sort()
    
            Dim firstNumber = list.First()
            Dim lastNumber = list.Last()
            Dim range = Enumerable.Range(firstNumber, lastNumber - firstNumber)
            Dim missingNumbers = range.Except(list)
            Return missingNumbers
        End Function
    End Module


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Saturday, March 3, 2018 12:30 AM
    Moderator
  • Assumes files are created in chronological order and that you are not filling the gaps:

        Private Function GetNextFileNumber() As Long
    
            Dim nextNumber As Long = 0
            Dim di As New DirectoryInfo(Application.StartupPath & "\_customers")
            Dim files() As FileSystemInfo = di.GetFileSystemInfos()
            Dim orderedFiles = files.OrderByDescending(Function(f) f.CreationTime)
    
            For Each fsi As FileSystemInfo In orderedFiles
                If fsi.Extension = ".txt" Then
                    nextNumber = CLng(Val(fsi.Name))
                    If nextNumber <> 0 Then
                        If Microsoft.VisualBasic.Strings.Left(fsi.Name, nextNumber.ToString.Length) = nextNumber.ToString() Then
                            Exit For
                        End If
                    End If
                End If
            Next
    
            Return nextNumber + 1
    
        End Function


    Paul ~~~~ Microsoft MVP (Visual Basic)



    Saturday, March 3, 2018 6:34 AM
  • Assumes files are created in chronological order and that you are not filling the gaps:

        Private Function GetNextFileNumber() As Long
    
            Dim nextNumber As Long = 0
            Dim di As New DirectoryInfo(Application.StartupPath & "\_customers")
            Dim files() As FileSystemInfo = di.GetFileSystemInfos()
            Dim orderedFiles = files.OrderByDescending(Function(f) f.CreationTime)
    
            For Each fsi As FileSystemInfo In orderedFiles
                If fsi.Extension = ".txt" Then
                    nextNumber = CLng(Val(fsi.Name))
                    If nextNumber <> 0 Then
                        If Microsoft.VisualBasic.Strings.Left(fsi.Name, nextNumber.ToString.Length) = nextNumber.ToString() Then
                            Exit For
                        End If
                    End If
                End If
            Next
    
            Return nextNumber + 1
    
        End Function


    Paul ~~~~ Microsoft MVP (Visual Basic)




    This code gets the last deleted file only. I tested it
    Saturday, March 3, 2018 11:41 AM
  • Here is another idea where if there is more than one missing we get that too.

    Imports System.IO
    
    Public Class Form3
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim intValues = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.txt").
                    ToList().
                    Select(Function(f)
                                Dim testInt As Integer = 0
                                if Integer.TryParse(Path.GetFileNameWithoutExtension(f) ,testInt) 
                                   Return testInt
                                Else 
                                   return nothing
                                End If                           
                           End Function).
                    ToList()
        
            Dim result = intValues.FindMissing()
            Console.WriteLine(String.Join(",", result))
            Console.WriteLine(result.OrderByDescending(Function(x) x).FirstOrDefault())
    
        End Sub
    End Class
    
    Public Module MyExtensions
        <Runtime.CompilerServices.Extension>
        Public Function FindMissing(ByVal list As List(Of Integer)) As IEnumerable(Of Integer)
            list.Sort()
    
            Dim firstNumber = list.First()
            Dim lastNumber = list.Last()
            Dim range = Enumerable.Range(firstNumber, lastNumber - firstNumber)
            Dim missingNumbers = range.Except(list)
            Return missingNumbers
        End Function
    End Module


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    I tested your code, it works fine getting the name of deleted files. But it doesn't work in the situation that the first file is deleted. I tested it with 5 files and I deleted the first and third one, it only got the third
    Saturday, March 3, 2018 12:18 PM
  • Try this too:

    Dim filename As String
    
    Dim filepath As String
    Dim i As Integer = 0
    Do
       i += 1
       filename = i & ".cinfo"
       filepath = Path.Combine(Application.StartupPath, "_customers", filename)
    Loop While File.Exists(filepath)
    
    MsgBox(filename)
    

    Saturday, March 3, 2018 1:51 PM
  • I must be misunderstanding what you mean by "deleted" file. The code can't get a file that does not exist. In your example, if a file starting with the number 5 exists and it was the last file created then the next number returned will be 6.

    The code also accounts for other files in the folder by checking that the numbers at the front are digits. It wasn't clear whether that was necessary but I added code to check. It probably would have helped to know whether the only files in the folder start with a number, in order to eliminate any code logic that was not necessary.

    I tested with the scenario you described below and the code works for me:

    The next number returned is 6.


    Paul ~~~~ Microsoft MVP (Visual Basic)

    Saturday, March 3, 2018 2:11 PM
  • In this example the first button creates 10 files. Check one or more then press the "Remove checked files", now press "Get missing to ListBox" and they will appear in the list box, press the last button and they appear in a MessageBox.

    I used a CheckedListBox for visuals while you would replace the CheckedListBox with a List(Of FileItem).

    Source code with four buttons, a CheckedListBox and a ListBox all with default names.

    Imports System.IO
    
    Public Class Form2
        Private sub SetupCheckListBox
    
            CheckedListBox1.Items.Clear()
    
            Dim itemList = new List(Of  FileItem)
            Dim result = Enumerable.Range(1,10).ToList().Select(Function(x) $"{x}.txt")
    
            For Each item As String In result
    
                itemList.Add(new FileItem() With{.Name = item})
    
                checkedListBox1.Items.Add(itemList.Last())
    
                File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,item),"")
    
            Next
    
        End sub
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            SetupCheckListBox
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            SetupCheckListBox()
        End Sub
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    
            for index as Integer = 0 to CheckedListBox1.Items.Count -1
    
                dim fileName as String = ""
    
                if CheckedListBox1.GetItemCheckState(index) = 1
                    fileName = CType(CheckedListBox1.Items(index),FileItem).FullName
                    if File.Exists(fileName)
                        File.Delete(fileName)
                    End If
                End If
    
            Next
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            ListBox1.Items.Clear()
            Dim checkItem As FileItem = nothing
            Dim fileName As String = ""
    
            for index as Integer = 0 to CheckedListBox1.Items.Count -1
                if CheckedListBox1.GetItemCheckState(index) = 1
    
                    checkItem = CType(CheckedListBox1.Items(index),FileItem)
                    fileName = checkItem.FullName
    
                    if not File.Exists(fileName)
                        ListBox1.Items.Add(checkItem.ConsoleInformation)
                    End If
                   
                End If
            Next
        End Sub
    
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            Dim nameList as new List(Of string)
    
            Dim checkItem As FileItem = nothing
            Dim fileName As String = ""
    
            for index as Integer = 0 to CheckedListBox1.Items.Count -1
                if CheckedListBox1.GetItemCheckState(index) = 1
    
                    checkItem = CType(CheckedListBox1.Items(index),FileItem)
                    fileName = checkItem.FullName
    
                    if not File.Exists(fileName)
                        nameList.Add(fileName)
                    End If
                   
                End If
            Next
    
            if nameList.Count >0
                MessageBox.Show(String.Join(Environment.NewLine,nameList.ToArray()))
            End If
        End Sub
    End Class
    ''' <summary>
    ''' This should be in a class file.
    ''' Some of the properties are needed only for demo purposes.
    ''' </summary>
    Public Class FileItem
        Public Property Name() As String
        Public ReadOnly Property Index As Integer
            get
                Dim testInt As Integer = 0
                if Integer.TryParse(Path.GetFileNameWithoutExtension(Name) ,testInt) 
                    Return testInt
                Else 
                    return -1
                End If                                       
            End get
        End Property
        ''' <summary>
        ''' assumes we are dealing with the executable folder, if not then
        ''' adjust as needed.
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property FullName() As string
            get
                Return Path.Combine(AppDomain.CurrentDomain.BaseDirectory,Name)
            End get
        End Property
        ' only for use with the CheckedListBox
        Public ReadOnly Property ConsoleInformation() As String
            get
                Return $"{Index}; {name}"
            End get
        End Property
        Public Overrides Function ToString() As String
            Return Name
        End Function
    End Class


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Saturday, March 3, 2018 2:56 PM
    Moderator
  • Hello.

    My app creates files in a folder, with numerical-based file names (for e.g. txt files : 1.txt , 2.txt , ...)

    So if there are 3 files, the forth file's name should be 4 . It is quite simple:

    Directory.GetFiles(Application.StartupPath & "\_customers\", "*.cinfo").Count + 1

    But when it comes to deleting a file among other files in the same folder , there will be problem. If there are 5 files and the forth is deleted , files are : 1.txt, 2.txt, 3.txt, 5.txt . Now with the code above, app creates  new file with the name 5 (5 already exists). App should follow the numerical pattern in creating new files.How to do the trick ?

    I would just use a simple loop like the following:

    Private Function GetNextFileId(path As String) As Integer
        Dim result As Integer = 1
        For Each id In (From f In IO.Directory.GetFiles(path, "*.txt") Select CInt(IO.Path.GetFileNameWithoutExtension(f)))
            If id = result Then
                result = id + 1
            Else
                Exit For
            End If
        Next
        Return result
    End Function
    


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Saturday, March 3, 2018 7:35 PM
    Moderator
  • Hello.

    My app creates files in a folder, with numerical-based file names (for e.g. txt files : 1.txt , 2.txt , ...)

    So if there are 3 files, the forth file's name should be 4 . It is quite simple:

    Directory.GetFiles(Application.StartupPath & "\_customers\", "*.cinfo").Count + 1

    But when it comes to deleting a file among other files in the same folder , there will be problem. If there are 5 files and the forth is deleted , files are : 1.txt, 2.txt, 3.txt, 5.txt . Now with the code above, app creates  new file with the name 5 (5 already exists). App should follow the numerical pattern in creating new files.How to do the trick ?

    The ListBox's Font is set to Consolas, a monospace Font, so all characters are the same size and therefore padding can be used to align the displayed data.

    You could easily write files to any available numbers also. You do not mention what numeric range you wanted to use for files names though.

    Option Strict On
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
        End Sub
    
        Dim Rand As New Random
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            For i = 1 To 100
                Dim RandomNr As Integer = Rand.Next(1, 2000)
                My.Computer.FileSystem.WriteAllText("C:\Users\John\Desktop\File Numbering Test\" & RandomNr.ToString & ".Txt", RandomNr.ToString, False)
            Next
        End Sub
    
        Dim FilesToDelete As New List(Of Integer)
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            ListBox1.Items.Clear()
            FilesToDelete.Clear()
            Dim LOS As New List(Of String)
            LOS = IO.Directory.GetFiles("C:\Users\John\Desktop\File Numbering Test").ToList
            For i = 0 To LOS.Count - 1
                If IsNumeric(IO.Path.GetFileNameWithoutExtension(LOS(i))) Then
                    FilesToDelete.Add(CInt(IO.Path.GetFileNameWithoutExtension(LOS(i))))
                End If
            Next
            FilesToDelete.Sort()
            If FilesToDelete.Count > 0 Then
                For i = 0 To FilesToDelete.Count - 1
                    For j = 0 To LOS.Count - 1
                        If CInt(IO.Path.GetFileNameWithoutExtension(LOS(j))) = FilesToDelete(i) Then
                            ListBox1.Items.Add(LOS(j).PadRight(55, " "c) & IO.Path.GetFileNameWithoutExtension(LOS(j)))
                        End If
                    Next
                Next
            End If
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            For i = 0 To FilesToDelete.Count - 1
                IO.File.Delete("C:\Users\John\Desktop\File Numbering Test\" & FilesToDelete(i).ToString & ".Txt")
            Next
        End Sub
    
    End Class


    La vida loca

    Sunday, March 4, 2018 3:18 AM
  • There's many methods that can be used.

    This creates 100 files randomly using the range of 1 to 2000. Button1 performs that.

    Button2 is for displaying the files in a DataGridView with a CheckBox column. The CheckBox's are used for selecting files to be deleted.

    Button3 is for deleting files who's paths are checked in the DataGridView.

    Button4 is for creating new files where open numbers exists, if any, using two NumericUpDown controls. This Button also performs a click on Button2 to relist the files.

    Option Strict On
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
            DataGridView1.ScrollBars = ScrollBars.Both
            DataGridView1.BackgroundColor = SystemColors.Control
            DataGridView1.BorderStyle = BorderStyle.None
            DataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect
            DataGridView1.Anchor = CType(AnchorStyles.Bottom + AnchorStyles.Left + AnchorStyles.Right + AnchorStyles.Top, AnchorStyles)
            DataGridView1.MultiSelect = False
            DataGridView1.AllowDrop = True
            DataGridView1.AutoSize = False
            DataGridView1.AllowUserToAddRows = False
            DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            DataGridView1.Font = New Font("Consolas", 11)
    
            Dim DGVCBC As New DataGridViewCheckBoxColumn
            DGVCBC.Name = "Row Select"
            DGVCBC.HeaderText = "Row Select"
            DataGridView1.Columns.Add(DGVCBC)
    
            DataGridView1.Columns.Add("Files", "Files")
    
            NumericUpDown1.Minimum = 1
            NumericUpDown1.Maximum = 1999
            NumericUpDown1.Value = 1
    
            NumericUpDown2.Minimum = 2
            NumericUpDown2.Maximum = 2000
            NumericUpDown2.Value = 2
    
        End Sub
    
        Dim Rand As New Random
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            For i = 1 To 100
                Dim RandomNr As Integer = Rand.Next(1, 2000)
                My.Computer.FileSystem.WriteAllText("C:\Users\John\Desktop\File Numbering Test\" & RandomNr.ToString & ".Txt", RandomNr.ToString, False)
            Next
        End Sub
    
        Dim FilesList As New List(Of String)
        Dim FilesToDelete As New List(Of Integer)
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            DataGridView1.Rows.Clear()
            FilesToDelete.Clear()
            FilesList.Clear()
            FilesList = IO.Directory.GetFiles("C:\Users\John\Desktop\File Numbering Test").ToList
            For i = 0 To FilesList.Count - 1
                If IsNumeric(IO.Path.GetFileNameWithoutExtension(FilesList(i))) Then
                    FilesToDelete.Add(CInt(IO.Path.GetFileNameWithoutExtension(FilesList(i))))
                End If
            Next
            FilesToDelete.Sort()
            If FilesToDelete.Count > 0 Then
                For i = 0 To FilesToDelete.Count - 1
                    For j = 0 To FilesList.Count - 1
                        If CInt(IO.Path.GetFileNameWithoutExtension(FilesList(j))) = FilesToDelete(i) Then
                            DataGridView1.Rows.Add(False, FilesList(j))
                        End If
                    Next
                Next
                DataGridView1.Columns(0).Width = 100
            End If
        End Sub
    
        Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
            If DataGridView1.Rows.Count > 0 Then
                For i = DataGridView1.Rows.Count - 1 To 0 Step -1
                    If DataGridView1.Rows(i).Cells(0).Value.ToString = "True" Then
                        MessageBox.Show(DataGridView1.Rows(i).Cells(1).Value.ToString)
                        IO.File.Delete(DataGridView1.Rows(i).Cells(1).Value.ToString)
                        DataGridView1.Rows.RemoveAt(i)
                    End If
                Next
            End If
        End Sub
    
        Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
            For i = NumericUpDown1.Value To NumericUpDown2.Value
                If IO.File.Exists("C:\Users\John\Desktop\File Numbering Test\" & i.ToString & ".Txt") = False Then
                    My.Computer.FileSystem.WriteAllText("C:\Users\John\Desktop\File Numbering Test\" & i.ToString & ".Txt", i.ToString, False)
                End If
            Next
            Button2.PerformClick()
        End Sub
    
        Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
            If NumericUpDown2.Value <= NumericUpDown1.Value Then
                NumericUpDown2.Value = NumericUpDown1.Value + 1
            End If
        End Sub
    
        Private Sub NumericUpDown2_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown2.ValueChanged
            If NumericUpDown1.Value >= NumericUpDown2.Value Then
                NumericUpDown1.Value = NumericUpDown2.Value - 1
            End If
        End Sub
    
    End Class


    La vida loca

    Sunday, March 4, 2018 4:47 AM