需要合并 2 个文件夹,每个文件夹中有数十万个文件。 VB.net

Need to merge 2 folders that have hundreds of thousands of files in each. VB.net

我需要合并这些文件夹,每个目录中都有大量文件。我会使用 folder.copy 但这需要很长时间。

我大部分时间都在使用 xcopy 进程来处理这个问题,但我一直收到 xcopy 的错误,说有 none 时有重复项。所以我试图找到一个与 xcopy 一样快甚至更快的可靠解决方案。

我之前试过的是:

Private Sub MergeF(ByVal TargetFolder As String, ByVal MergeeFolder As String)
    For Each F As String In IO.Directory.GetFiles(MergeeFolder)
        If IO.File.Exists(IO.Path.Combine(TargetFolder, IO.Path.GetFileName(F))) Then
            Dim FileA As New IO.FileInfo(IO.Path.Combine(
                MergeeFolder, IO.Path.GetFileName(F)))
            Dim FileB As New IO.FileInfo(IO.Path.Combine(
                TargetFolder, IO.Path.GetFileName(F)))
            If FileA.Length <> FileB.Length Then
                Dim index As Integer = 1
                Do
                    Dim NewFileName = IO.Path.Combine(TargetFolder,
                        IO.Path.GetFileName(F.Insert(F.Length - 4, CStr(index))))
                    If IO.File.Exists(NewFileName) Then
                        index += 1
                    Else
                        IO.File.Copy(F, NewFileName)
                        IO.File.Delete(F)
                        Exit Do
                    End If
                Loop
            End If
        Else
            IO.File.Move(IO.Path.Combine(MergeeFolder, IO.Path.GetFileName(F)),
                IO.Path.Combine(TargetFolder, IO.Path.GetFileName(F)))
        End If
    Next
End Sub

https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-copy-directories

异步也应该加快速度;

https://docs.microsoft.com/en-us/dotnet/standard/io/asynchronous-file-i-o

如果这还不够快,那么我认为您的下一个选择是尝试直接使用 win32api

将代码转换为 vb 您可以使用;

https://codeconverter.icsharpcode.net/ 要么 https://converter.telerik.com/

  • 祝你好运!

您的实现问题在于您在循环内调用 File.Exists。这会一次又一次地扫描目标目录中的文件并使其变慢。更好的方法是将目标目录中文件的文件名加载到HashSet(Of T)中。此集合中的查找速度非常快 - 比 File.Exists.

快得多
Private Sub MergeF(ByVal TargetFolder As String, ByVal MergeeFolder As String)
    Dim targetFiles = New HashSet(Of String)(
        IO.Directory.GetFiles(TargetFolder) _
            .Select(Function(f) IO.Path.GetFileName(f)),
        StringComparer.OrdinalIgnoreCase)

    For Each sourcePath As String In IO.Directory.GetFiles(MergeeFolder)
        Dim file As String = IO.Path.GetFileName(sourcePath)
        Dim targetPath As String = IO.Path.Combine(TargetFolder, file)

        If targetFiles.Contains(file) Then
            Dim sourceInfo As New IO.FileInfo(sourcePath)
            Dim targetInfo As New IO.FileInfo(targetPath)
            If sourceInfo.Length <> targetInfo.Length Then
                Dim index As Integer = 1
                Do
                    Dim fileWithoutExt =
                    Path.GetFileNameWithoutExtension(file)
                    Dim extension = Path.GetExtension(file)
                    file = fileWithoutExt & index & extension
                    If targetFiles.Contains(file) Then
                        index += 1
                    Else
                        targetPath = IO.Path.Combine(TargetFolder, file)
                        targetFiles.Add(file) 'Upate the HashSet
                        IO.File.Move(sourcePath, targetPath)
                        Exit Do
                    End If
                Loop
            End If
        Else
            targetFiles.Add(file) 'Upate the HashSet
            IO.File.Move(sourcePath, targetPath)
        End If
    Next
End Sub

请注意,我还通过使用适当的变量减少了 Path.CombinePath.GetFileName 的数量。我调用了不带目录的文件名 ...File 和完整路径 ...Path.

我用 StringComparer.OrdinalIgnoreCase 初始化 HashSet,使其忽略文件名的字符大小写,因为 Windows 文件系统也忽略大小写。