Можно ли уменьшить количество нумерации файлов?

Я написал это в VB.NET, но я тоже доволен C#. У меня есть список файлов, которые я хочу найти в файловой системе Windows. Основываясь на имени файла, мне нужно будет искать в другом каталоге. Список файлов, которые у меня есть, это список, который я скомпилировал в начале программы (который работает), и он хранится в DataTable, который не отсортирован. Вот мой подход.

Список файлов DataTable (может варьироваться изо дня в день, иногда в тысячах +)

- a_111.txt
- a_222.txt
- b_333.txt
- a_444.txt
- c_555.txt
- b_666.txt

Каталоги для просмотра на основе имени файла

C:\a\ -- for files begin with a (variable name is A_folder)
C:\b\ -- for files begin with b (variable name is B_folder)
C:\c\ -- for files begin with c (variable name is C_folder)

Код:

If DataTableofFiles IsNot Nothing AndAlso DataTableofFiles.Rows.Count > 0 Then 
  For Each row as DataRow In DataTableofFiles.Rows
    If row("FILENAME").ToString.StartsWith("a") Then
      Dim a_WriteResultstoA as String = "a.csv"
      functionfindfiles(A_folder, row("FILENAME").ToString, a_WriteResultstoA)
    ElseIf row("FILENAME").ToString.StartsWith("b") Then
      Dim b_WriteResultstoB as String = "b.csv"
      functionfindfiles(B_folder, row("FILENAME").ToString, b_WriteResultstoB)
    ElseIf row("FILENAME").ToString.StartsWith("C") Then
      Dim c_WriteResultstoC as String = "c.csv"
      functionfindfiles(C_folder, row("FILENAME").ToString, c_WriteResultstoC)
    End If
  Next
End If

Private Sub functionfindfiles(sourcefolder As String, filename as String, writetofile As String)
        Try
            For Each f As String In Directory.EnumerateFiles(sourcefolder, "*.*", SearchOption.AllDirectories)  '<-- file enumeration
                    If Path.GetFileName(f).Equals(filename, StringComparison.OrdinalIgnoreCase) Then
                        Using fs As New FileStream(writetofile, FileMode.Append, FileAccess.Write, FileShare.Write)
                            Using sw As StreamWriter = New StreamWriter(fs)
                                If Not New FileInfo(writetofile).Length > 0 Then
                                    For i As Integer = 0 To DataTableofFiles.Columns.Count - 1 Step 1
                                        sw.Write(DataTableofFiles.Columns(i).ToString)

                                        If i < DataTableofFiles.Columns.Count - 1 Then
                                            sw.Write(",")
                                        End If
                                    Next

                                    sw.WriteLine()
                                End If

                                For Each row As DataRow In DataTableofFiles.Rows
                                    If row("FILENAME").ToString = filename Then
                                        For i As Integer = 0 To DataTableofFiles.Columns.Count - 1 Step 1
                                            If Not Convert.IsDBNull(row(i)) Then
                                                sw.Write(row(i).ToString.Replace(vbLf, "").Replace(",", ";"))
                                            End If

                                            If i < DataTableofFiles.Columns.Count - 1 Then
                                                sw.Write(",")
                                            End If
                                        Next

                                        sw.WriteLine()
                                    End If
                                Next
                            End Using
                        End Using
                    Else
                        'write results that are not found here to a file
                    End If
            Next
        Catch ex As Exception
    MessageBox.Show(ex.Message)
        End Try
End Sub

В этом случае перечисление в файловой системе произойдет 6 раз. Выполнение может занять очень много времени, если у меня много файлов в каталогах. Есть ли лучший подход, который уменьшит количество файловых перечислений? Или другие области в коде, которые можно улучшить, чтобы уменьшить количество дополнительных операций, выполняемых больше, чем нужно? Любые советы высоко ценится. Спасибо!

1 ответ

Решение

Вы не перечисляете 6 раз в вашем примере, вы перечисляете папку A 3 раза, папка B 2 раза и папка C 1 раз. Чтобы уменьшить эти дополнительные перечисления, вы можете предварительно обработать таблицу данных для создания списков имен файлов для каждой папки, а затем изменить свой метод для работы со списком имен файлов вместо одного имени файла. Я не пишу на VB, так что вот ответ, который мешает в коде C# (извините, я не смог уместить мои идеи в комментарии, это плохой ответ, так как он не компилируется).

Обратите внимание, что все, что я сделал с вашим методом, было добавлено в foreach (var filename in listOfFileNames) и изменил подпись, чтобы принять List<string> listOfFileNames вместо просто string filenameи вызывающая сторона теперь строит списки и завершает обработку данных foreach полностью перед вызовом метода один раз для каждой папки.

If DataTableofFiles IsNot Nothing AndAlso DataTableofFiles.Rows.Count > 0 Then 

  List<string> allAFileNames = new List<string>();
  List<string> allBFileNames = new List<string>();
  List<string> allCFileNames = new List<string>();

  For Each row as DataRow In DataTableofFiles.Rows
    If row("FILENAME").ToString.StartsWith("a") Then
      Dim a_WriteResultstoA as String = "a.csv"

      allAFileNames.Add(row("FILENAME"));

    ElseIf row("FILENAME").ToString.StartsWith("b") Then
      Dim b_WriteResultstoB as String = "b.csv"

      allBFileNames.Add(row("FILENAME"));

    ElseIf row("FILENAME").ToString.StartsWith("C") Then
      Dim c_WriteResultstoC as String = "c.csv"

      allCFileNames.Add(row("FILENAME"));

    End If
  Next

  if (allAFileNames.Count > 0)
  {
        functionfindfiles(A_folder, allAFileNames, a_WriteResultstoA);
  }

  if (allBFileNames.Count > 0)
  {
        functionfindfiles(B_folder, allBFileNames, b_WriteResultstoB)
  }

  if (allAFileNames.Count > 0)
  {
        functionfindfiles(C_folder, allCFileNames, c_WriteResultstoC)
  }

End If

Private Sub functionfindfiles(sourcefolder As String, List<string> listOfFileNames, writetofile As String)
        Try
            For Each f As String In Directory.EnumerateFiles(sourcefolder, "*.*", SearchOption.AllDirectories)  '<-- file enumeration

                    foreach (var filename in listOfFileNames)
                    {

                    If Path.GetFileName(f).Equals(filename, StringComparison.OrdinalIgnoreCase) Then
                        Using fs As New FileStream(writetofile, FileMode.Append, FileAccess.Write, FileShare.Write)
                            Using sw As StreamWriter = New StreamWriter(fs)
                                If Not New FileInfo(writetofile).Length > 0 Then
                                    For i As Integer = 0 To DataTableofFiles.Columns.Count - 1 Step 1
                                        sw.Write(DataTableofFiles.Columns(i).ToString)

                                        If i < DataTableofFiles.Columns.Count - 1 Then
                                            sw.Write(",")
                                        End If
                                    Next

                                    sw.WriteLine()
                                End If

                                For Each row As DataRow In DataTableofFiles.Rows
                                    If row("FILENAME").ToString = filename Then
                                        For i As Integer = 0 To DataTableofFiles.Columns.Count - 1 Step 1
                                            If Not Convert.IsDBNull(row(i)) Then
                                                sw.Write(row(i).ToString.Replace(vbLf, "").Replace(",", ";"))
                                            End If

                                            If i < DataTableofFiles.Columns.Count - 1 Then
                                                sw.Write(",")
                                            End If
                                        Next

                                        sw.WriteLine()
                                    End If
                                Next
                            End Using
                        End Using
                    Else
                        'write results that are not found here to a file
                    End If
                    }
            Next
        Catch ex As Exception
    MessageBox.Show(ex.Message)
        End Try
End Sub
Другие вопросы по тегам