⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filecopy.vb

📁 文件复制器 2007.07.28.0最新VB源代码 地狱门神(F.R.C.) 适用范围 Windows环境下
💻 VB
📖 第 1 页 / 共 3 页
字号:
'==========================================================================
'
'  File:        FileCopy.vb
'  Location:    FileCopier <Visual Basic .Net>
'  Description: 文件复制模块
'  Version:     2007.07.28.
'  Copyright(C) F.R.C.
'
'==========================================================================

Option Compare Text
Imports System
Imports System.Math
Imports System.Collections.Generic
Imports System.IO
Imports System.Data

Public Class FileCopy

#Region " 选项和参数 "
    Enum SameFileIdentifierOption
        Path = 1
        First64K = 2
        FullFile = 4
        CorrectWriteTimeOffsetIn2s = 8
    End Enum
    Enum CreateTimeAndCharCaseHandlingOption
        Source
        Target
        Earlier
    End Enum
    Enum DifferentFileHandlingOption
        Backup
        CopyNew
    End Enum

    Public SameFileIdentifier As SameFileIdentifierOption
    Public CreateTimeAndCharCaseHandling As CreateTimeAndCharCaseHandlingOption
    Public DifferentFileHandling As DifferentFileHandlingOption
    Public PreserveDeleted As Boolean
    Sub SetFileCopyOption(ByVal SameFileIdentifier As SameFileIdentifierOption, ByVal CreateTimeAndCharCaseHandling As CreateTimeAndCharCaseHandlingOption, ByVal DifferentFileHandling As DifferentFileHandlingOption, ByVal PreserveDeleted As Boolean)
        Me.SameFileIdentifier = SameFileIdentifier
        Me.CreateTimeAndCharCaseHandling = CreateTimeAndCharCaseHandling
        Me.DifferentFileHandling = DifferentFileHandling
        Me.PreserveDeleted = PreserveDeleted
    End Sub

    Public SourceDir As String
    Public TargetDir As String
    Public NewDir As String
    Public BackupDir As String
    Public ExceptionalDir As String
    Public LogPath As String
    Public Filters As String()
    Sub SetFileCopyParameter(ByVal SourceDir As String, ByVal TargetDir As String, ByVal NewDir As String, ByVal BackupDir As String, ByVal ExceptionalDir As String, ByVal LogPath As String, ByVal Filters As String())
        Me.SourceDir = SourceDir
        Me.TargetDir = TargetDir
        Me.NewDir = NewDir
        Me.BackupDir = BackupDir
        Me.ExceptionalDir = ExceptionalDir
        Me.LogPath = LogPath
        Me.Filters = Filters
    End Sub

    Protected LogFile As StreamWriter
    Sub LogOpen(ByVal Append As Boolean)
        If LogPath = "" Then Return
        If Not IO.Directory.Exists(GetFileDirectory(LogPath)) Then IO.Directory.CreateDirectory(GetFileDirectory(LogPath))
        LogFile = New StreamWriter(LogPath, Append, Text.Encoding.Default)
    End Sub
    Sub LogWriteLine()
        If Not LogFile Is Nothing Then LogFile.WriteLine()
    End Sub
    Sub LogWriteLine(ByVal s As String)
        If Not LogFile Is Nothing Then LogFile.WriteLine(s)
    End Sub
    Sub LogWriteLine(ByVal s As String, ByVal arg0 As Object)
        If Not LogFile Is Nothing Then LogFile.WriteLine(s, arg0)
    End Sub
    Sub LogWriteLine(ByVal s As String, ByVal arg0 As Object, ByVal arg1 As Object)
        If Not LogFile Is Nothing Then LogFile.WriteLine(s, arg0, arg1)
    End Sub
    Sub LogWrite(ByVal s As String)
        If Not LogFile Is Nothing Then LogFile.Write(s)
    End Sub
    Sub LogWrite(ByVal s As String, ByVal arg0 As Object)
        If Not LogFile Is Nothing Then LogFile.Write(s, arg0)
    End Sub
    Sub LogWrite(ByVal s As String, ByVal arg0 As Object, ByVal arg1 As Object)
        If Not LogFile Is Nothing Then LogFile.Write(s, arg0, arg1)
    End Sub
    Sub LogClose()
        If Not LogFile Is Nothing Then LogFile.Close()
    End Sub
#End Region

    Protected MappingTable As List(Of ActionFile)
    Protected MappingTableDirs As List(Of ActionDir)
    Public Delegate Sub ProgressEventHandler(ByVal Value As Double, ByVal Status As String)

#Region " 可行性分析 "
    Sub AnalyzeFeasibility(ByVal PreCopyCmds As String(), ByRef Output As String, Optional ByVal ChangeProgress As ProgressEventHandler = Nothing)
#If CONFIG <> "Debug" Then
        Try
#End If
        LogOpen(False)
        LogWriteLine("----------------")
        LogWriteLine(DateAndTime.Now & " " & TimeZone.CurrentTimeZone.GetUtcOffset(DateAndTime.Now).TotalHours.ToString("+##.#;-##.#"))
        LogWriteLine("------PreCopy批处理------")
        Dim PreCopyResult As String = ExecuteCmds("PreCopy.cmd", PreCopyCmds)
        Output = "------PreCopy批处理------" & Environment.NewLine & PreCopyResult
        Application.DoEvents()
        LogWriteLine("------可行性报告------")
        If SourceDir = "" Then Throw New InvalidDataException("源文件夹路径不正确。")
        If Not Directory.Exists(SourceDir) Then Throw New InvalidDataException("源文件夹不存在。")
        LogWriteLine("源文件夹 {0}", SourceDir)
        If TargetDir = "" Then Throw New InvalidDataException("目标文件夹路径不正确。")
        If Not Directory.Exists(TargetDir) Then Directory.CreateDirectory(TargetDir)
        LogWriteLine("目标文件夹 {0}", TargetDir)
        If DifferentFileHandling = DifferentFileHandlingOption.Backup Then
            If BackupDir = "" Then Throw New InvalidDataException("备份文件夹路径不正确。")
            If Not Directory.Exists(BackupDir) Then Directory.CreateDirectory(BackupDir)
            LogWriteLine("备份文件夹 {0}", BackupDir)
            If ExceptionalDir = "" Then Throw New InvalidDataException("异常文件夹路径不正确。")
            If Not Directory.Exists(ExceptionalDir) Then Directory.CreateDirectory(ExceptionalDir)
            LogWriteLine("异常文件夹 {0}", ExceptionalDir)
        Else 'If DifferentFileHandling = DifferentFileHandlingOption.CopyNew Then
            If NewDir = "" Then Throw New InvalidDataException("更新文件夹路径不正确。")
            If Not Directory.Exists(NewDir) Then Directory.CreateDirectory(NewDir)
            LogWriteLine("更新文件夹 {0}", NewDir)
        End If
        LogWriteLine()

        GenerateDataTable(ChangeProgress)
        LogWriteLine("------文件映射表------")
        GenerateMappingTable(ChangeProgress)

        Dim s As New Text.StringBuilder
        s.AppendLine("------可行性报告------")
        If CalculateDiskSpace(s) Then
            s.AppendLine()
            s.AppendLine("可行")
        Else
            s.AppendLine()
            s.AppendLine("不可行")
        End If
        s.AppendLine()
        s.AppendLine("请自行确保所有需要写操作的磁盘可写。")
        s.AppendLine()
        s.AppendLine("请自行确保所有涉及的文件的句柄已经释放。")
        s.AppendLine("可使用Unlocker之类的软件确认。")
        s.AppendLine()
        s.AppendLine("请关掉杀毒软件,防止杀毒软件删除文件导致错误。")

        LogWriteLine(s.ToString)
        LogWriteLine("----------------")
        LogClose()

        Output = PreCopyResult & s.ToString
        Application.DoEvents()
#If CONFIG <> "Debug" Then
        Catch ex As Exception
            LogWriteLine()
            LogWriteLine(ex.ToString)
            LogClose()
            Throw
        End Try
#End If
    End Sub

#Region " 生成文件数据表及文件映射表 "
    Protected SourceDirs As DataTable
    Protected TargetDirs As DataTable
    Protected Source As DataTable
    Protected Target As DataTable
    Protected Sub GenerateDataTable(Optional ByVal ChangeProgress As ProgressEventHandler = Nothing)
        SourceDirs = New DataTable()
        SourceDirs.CaseSensitive = False
        SourceDirs.Columns.Add("Name", GetType(System.String))
        SourceDirs.Columns.Add("Path", GetType(System.String))
        SourceDirs.PrimaryKey = New DataColumn() {SourceDirs.Columns("Path")}

        TargetDirs = New DataTable()
        TargetDirs.CaseSensitive = False
        TargetDirs.Columns.Add("Name", GetType(System.String))
        TargetDirs.Columns.Add("Path", GetType(System.String))
        TargetDirs.PrimaryKey = New DataColumn() {TargetDirs.Columns("Path")}

        Source = New DataTable()
        Source.CaseSensitive = False
        Source.Columns.Add("Name", GetType(System.String))
        Source.Columns.Add("Length", GetType(System.Int64))
        Source.Columns.Add("WriteTime", GetType(System.Int64))
        Source.Columns.Add("Path", GetType(System.String))
        Source.PrimaryKey = New DataColumn() {Source.Columns("Path")}

        Target = New DataTable()
        Target.CaseSensitive = False
        Target.Columns.Add("Name", GetType(System.String))
        Target.Columns.Add("Length", GetType(System.Int64))
        Target.Columns.Add("WriteTime", GetType(System.Int64))
        Target.Columns.Add("Path", GetType(System.String))
        Target.PrimaryKey = New DataColumn() {Target.Columns("Path")}

        If ChangeProgress IsNot Nothing Then ChangeProgress(0, "生成文件信息表(1/2)")
        AddDirToSourceDirs(SourceDir)
        If ChangeProgress IsNot Nothing Then ChangeProgress(0.05, Nothing)
        AddDirToTargetDirs(TargetDir)
        If ChangeProgress IsNot Nothing Then ChangeProgress(0.1, Nothing)
        AddDirToSource(SourceDir)
        If ChangeProgress IsNot Nothing Then ChangeProgress(0.55, Nothing)
        AddDirToTarget(TargetDir)
        If ChangeProgress IsNot Nothing Then ChangeProgress(1, Nothing)
    End Sub
    Protected Sub GenerateMappingTable(Optional ByVal ChangeProgress As ProgressEventHandler = Nothing)
        '按照相同文件、已修改文件、异常文件、删除文件、更新文件的顺序排列映射表
        '可以使得目标文件的空间使用先减小后增大
        '在同一路径已有不同文件的情况下不再寻找相同文件,避免路径冲突

        Dim DIVer As Integer = Source.Rows.Count + Target.Rows.Count
        Dim DIVee As Integer = 0

        If ChangeProgress IsNot Nothing Then ChangeProgress(0, "生成文件映射表(2/2)")
        MappingTable = New List(Of ActionFile)
        Dim a As ActionFile
        Dim n As Integer = 0
        While n < Source.Rows.Count
            Dim s As DataRow = Source.Rows(n)
            Dim Selected As DataRow() = Target.Select(String.Format("Path = '{0}'", Escape(s("Path"))))
            If Selected Is Nothing OrElse Selected.Length = 0 Then
                n += 1
                Continue While
            End If
            If Selected.Length = 1 Then
                Dim t As DataRow = Selected(0)
                If IsSameFile(s, t) Then
                    a = New ActionFile(s, t, ActionTypeEnum.Same)
                    LogWriteLine("Same {0} -> {1}", a.Source.Path, a.Target.Path)
                    MappingTable.Add(a)
                Else
                    If DateTime.FromBinary(s.Item("WriteTime")) > DateTime.FromBinary(t.Item("WriteTime")) Then
                        a = New ActionFile(s, t, ActionTypeEnum.Refresh)
                        LogWriteLine("Refresh {0} -> {1}", a.Source.Path, a.Target.Path)
                        MappingTable.Add(a)
                    Else
                        a = New ActionFile(s, t, ActionTypeEnum.Revert)
                        LogWriteLine("Revert {0} -> {1}", a.Source.Path, a.Target.Path)
                        MappingTable.Add(a)
                    End If
                End If
                Source.Rows.Remove(s)
                Target.Rows.Remove(t)
                If ChangeProgress IsNot Nothing Then
                    DIVee += 2
                    ChangeProgress(DIVee / DIVer, Nothing)
                End If
            Else
                Throw New InvalidOperationException
            End If
        End While

        If Not (SameFileIdentifier And SameFileIdentifierOption.Path) Then
            n = 0
            While n < Source.Rows.Count
                Dim s As DataRow = Source.Rows(n)
                Dim Selected As DataRow() = Target.Select(String.Format("Name = '{0}' AND Length = {1}", Escape(s("Name")), s("Length")))
                If Selected Is Nothing OrElse Selected.Length = 0 Then
                    n += 1
                    Continue While
                End If
                Dim t As DataRow = GetBestFitted(s, Selected) '极端情况下可能遗漏真正符合的
                If IsSameFile(s, t) Then
                    a = New ActionFile(s, t, ActionTypeEnum.Same)
                    LogWriteLine("Same {0} -> {1}", a.Source.Path, a.Target.Path)
                    MappingTable.Add(a)
                    Source.Rows.Remove(s)
                    Target.Rows.Remove(t)
                    If ChangeProgress IsNot Nothing Then
                        DIVee += 2
                        ChangeProgress(DIVee / DIVer, Nothing)
                    End If
                Else
                    n += 1
                End If
            End While
        End If

        If Not PreserveDeleted Then
            For Each t As DataRow In Target.Rows
                a = New ActionFile(Nothing, t, ActionTypeEnum.Delete)
                LogWriteLine("Delete NULL -> {0}", a.Target.Path)
                MappingTable.Add(a)
                If ChangeProgress IsNot Nothing Then
                    DIVee += 1
                    ChangeProgress(DIVee / DIVer, Nothing)
                End If
            Next
        End If
        For Each s As DataRow In Source.Rows
            a = New ActionFile(s, Nothing, ActionTypeEnum.Create)
            LogWriteLine("Create {0} -> NULL", a.Source.Path)
            MappingTable.Add(a)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -