是否可以减少文件编号?
Is it possible to reduce number of file numeration?
我在 VB.NET 中写了这篇文章,但我对 C# 也很满意。我有一个要在 Windows 文件系统上查找的文件列表。根据文件名,我需要在不同的目录中查找。我拥有的文件列表是我在程序开始时编译的列表(有效),它存储在未排序的 DataTable 中。这是我的方法。
DataTable 文件列表(这可能每天都在变化,有时在 1,000s+)
- 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次。如果目录中有很多文件,执行可能会花费很长时间。有没有更好的方法可以减少文件枚举的数量?或者代码中的其他区域可以改进以减少执行超出需要的额外操作?任何意见是极大的赞赏。谢谢!
您在示例中没有枚举 6 次,而是枚举文件夹 A
3 次,文件夹 B
2 次,文件夹 C
1 次。为了减少这些额外的枚举,您可以预处理数据 table 以构建每个文件夹的文件名列表,然后修改您的方法以处理文件名列表而不是单个文件名。我不写 VB 所以这是一个混搭在 c# 代码中的答案(抱歉我无法将我的想法放入评论中,这是一个糟糕的答案,因为它无法编译)。
请注意,我对您的方法所做的只是添加 foreach (var filename in listOfFileNames)
并更改签名以接受 List<string> listOfFileNames
而不仅仅是 string filename
,调用者现在构建列表并完成数据table 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
我在 VB.NET 中写了这篇文章,但我对 C# 也很满意。我有一个要在 Windows 文件系统上查找的文件列表。根据文件名,我需要在不同的目录中查找。我拥有的文件列表是我在程序开始时编译的列表(有效),它存储在未排序的 DataTable 中。这是我的方法。
DataTable 文件列表(这可能每天都在变化,有时在 1,000s+)
- 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次。如果目录中有很多文件,执行可能会花费很长时间。有没有更好的方法可以减少文件枚举的数量?或者代码中的其他区域可以改进以减少执行超出需要的额外操作?任何意见是极大的赞赏。谢谢!
您在示例中没有枚举 6 次,而是枚举文件夹 A
3 次,文件夹 B
2 次,文件夹 C
1 次。为了减少这些额外的枚举,您可以预处理数据 table 以构建每个文件夹的文件名列表,然后修改您的方法以处理文件名列表而不是单个文件名。我不写 VB 所以这是一个混搭在 c# 代码中的答案(抱歉我无法将我的想法放入评论中,这是一个糟糕的答案,因为它无法编译)。
请注意,我对您的方法所做的只是添加 foreach (var filename in listOfFileNames)
并更改签名以接受 List<string> listOfFileNames
而不仅仅是 string filename
,调用者现在构建列表并完成数据table 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