修复此方法中合并文件的进度报告

时间:2014-08-15 15:52:53

标签: .net vb.net math byte progress

我编写了一个将文件拆分为小块(here)的方法,这是合并这些拆分块的方法。

我遇到的问题是进度报告,ChunkProgress值的计算错误:

enter image description here

每个块应该从0%到100%。

我该如何解决?

这就是我获得价值的方式:

ChunkProgress = (100I / InputStream.Length) * (SizeWritten - BufferLength)
  

InputStream.Length =当前块的大小(以字节为单位)。

     

SizeWritten =来自第一个块的写入字节总数。

     

BufferLength =用于读/写字节的固定缓冲区大小(在本例中为1兆字节)

这是相关代码:

''' <summary>
''' Gets or sets the buffer-size to split or merge, in Bytes.
''' Default value is: 1048576 bytes (1 megabyte).
''' </summary>
''' <value>The buffer-size.</value>
Public Property BufferSize As Integer = 1048576I


''' <summary>
''' Merges the specified file.
''' </summary>
''' <param name="InputFile">
''' Indicates the file to merge its chunks.
''' This should be the first chunk file (eg: 'File.Part.01.mkv')
''' </param>
''' <param name="OutputFile">Indicates the output file.</param>
''' <param name="Overwrite">
''' If set to <c>true</c> the chunks will be deleted after a successful merge, 
''' otherwise, an exception will be thrown.
''' </param>
''' <exception cref="System.IO.IOException">File already exist</exception>
Public Sub Merge(ByVal InputFile As String,
                 Optional ByVal OutputFile As String = Nothing,
                 Optional ByVal Overwrite As Boolean = False,
                 Optional DeleteChunksAfterMerged As Boolean = False)

    If Not File.Exists(InputFile) Then
        Throw New FileNotFoundException("The specified file doesn't exists.", InputFile)
        Exit Sub

    ElseIf Not Overwrite AndAlso File.Exists(OutputFile) Then
        Throw New IOException(String.Format("File already exist: {0}", OutputFile))
        Exit Sub

    End If

    ' The progress event arguments.
    Dim ProgressArguments As MergeProgressChangedArgs

    ' FileInfo instance of the input chunk file.
    Dim fInfo As New FileInfo(InputFile)

    ' Get the filename without extension.
    Dim Filename As String = Path.GetFileNameWithoutExtension(fInfo.FullName)
    ' Remove the chunk enumeration from the filename.
    Filename = Filename.Substring(0I, Filename.LastIndexOf("."c))

    ' TSet the pattern to find the chunk files to merge.
    Dim ChunkPatternSearch As String =
        Filename & ".*" & If(Not String.IsNullOrEmpty(fInfo.Extension), fInfo.Extension, "")

    ' Retrieve all the splitted files to merge them.
    Dim Chunks As IEnumerable(Of FileInfo) =
       From Chunk As String In
       Directory.GetFiles(fInfo.DirectoryName, ChunkPatternSearch, SearchOption.TopDirectoryOnly)
       Select New FileInfo(Chunk)

    ' The total filesize to merge, in bytes.
    Dim TotalSize As Long =
        (From Chunk As FileInfo In Chunks Select Chunk.Length).Sum

    ' The remaining size to calculate the percentage, in bytes.
    Dim SizeRemaining As Long = TotalSize

    ' Counts the length of the current chunk file to calculate the percentage, in bytes.
    Dim SizeWritten As Long = 0L

    ' The buffer to read data and merge the chunks.
    Dim Buffer As Byte() = New Byte() {}

    ' The buffer length.
    Dim BufferLength As Integer = Me.BufferSize

    ' The total amount of chunks to merge.
    Dim ChunkCount As Integer = Chunks.Count

    ' Keeps track of the current chunk.
    Dim ChunkIndex As Integer = 0I

    ' Keeps track of the total percentage done.
    Dim TotalProgress As Double = 0.0R

    ' Keeps track of the current chunk percentage done.
    Dim ChunkProgress As Double = 0.0R

    ' Create the output file to merge the chunks inside.
    Using OutputStream As New FileStream(OutputFile, FileMode.Create)

        Using BinaryWriter As New BinaryWriter(OutputStream)

            ' Iterate the chunks.
            For Each Chunk As FileInfo In Chunks

                ' Open the chunk to start reading bytes.
                Using InputStream As New FileStream(Chunk.FullName, FileMode.Open)

                    Using BinaryReader As New BinaryReader(InputStream)

                        ' Read until reached the end-bytes of the chunk file.
                        While (InputStream.Position < InputStream.Length)

                            ' Read bytes from the chunk file (BufferSize byte-length).
                            Buffer = BinaryReader.ReadBytes(BufferLength)

                            ' Write those bytes in the output file.
                            BinaryWriter.Write(Buffer)

                            ' Increment the bytes-written counter.
                            SizeWritten += Buffer.Count

                            ' Decrease the bytes-remaining counter.
                            SizeRemaining -= Buffer.Count

                            TotalProgress = (TotalSize - SizeRemaining) * (100I / TotalSize)
                            ChunkProgress = (100I / InputStream.Length) * (SizeWritten - BufferLength)
                            ' (100I / InputStream.Length) * (SizeWritten - BufferLength)

                            ' Set the progress event-arguments.
                            ProgressArguments = New MergeProgressChangedArgs(
                                TotalProgress:=TotalProgress,
                                ChunkProgress:=ChunkProgress,
                                ChunksToMerge:=ChunkCount,
                                ChunksMerged:=ChunkIndex)

                            ' Report the progress.
                            RaiseEvent MergeProgressChanged(Me, ProgressArguments)

                        End While ' (InputStream.Position < InputStream.Length)

                        ChunkIndex += 1I 'Increment the chunk file counter.

                    End Using ' BinaryReader

                End Using ' InputStream

            Next Chunk

            OutputStream.Flush()

        End Using ' BinaryWriter

    End Using ' OutputStream

    If DeleteChunksAfterMerged Then ' Delethe the chunk files.

        For Each Chunk As FileInfo In Chunks
            File.Delete(Chunk.FullName)
        Next Chunk

    End If ' DeleteChunksAfterMerged

End Sub

1 个答案:

答案 0 :(得分:2)

您需要这个来计算整个文件的百分比:

' Increment the bytes-written counter.
   SizeWritten += Buffer.Count

但它在报告块进度方面没有任何作用。如果你看一下GIF,你会在它开始编写块#2的那一刻看到它提示超过100%,然后当你开始做块3时再次提示为200%。要修复它,你需要一个新的ChunkBytesWritten类型var:

' Increment the bytes-written counter.
 SizeWritten += Buffer.Count
 ChunkBytes+= Buffer.Count

然后在ChunkIndex更改时重置它:

ChunkIndex += 1
ChunkBytes = 0

然后计算应该是:

ChunkProgress = (100I / InputStream.Length) * (ChunkBytes - BufferLength)