.net 修复此方法中的进度报告事件
我曾尝试编写一种方法,将文件拆分为更小的部分(我称这些部分为“块”),我使用1 MB的缓冲区读取/写入块,并报告操作进度百分比和当前块进度百分比 问题是,我有一个6,74 GB的大文件,我会将它分成每个1 GB的块,进度报告按预期工作,但不适用于最后一个块,其中进度仅高达75%。当然,最后一个部分约为750 mb,而不是1 GB,那么最后一个块中的进度仅显示为75% 这就是我获取百分比的方式,错误的进度是.net 修复此方法中的进度报告事件,.net,vb.net,math,byte,progress,.net,Vb.net,Math,Byte,Progress,我曾尝试编写一种方法,将文件拆分为更小的部分(我称这些部分为“块”),我使用1 MB的缓冲区读取/写入块,并报告操作进度百分比和当前块进度百分比 问题是,我有一个6,74 GB的大文件,我会将它分成每个1 GB的块,进度报告按预期工作,但不适用于最后一个块,其中进度仅高达75%。当然,最后一个部分约为750 mb,而不是1 GB,那么最后一个块中的进度仅显示为75% 这就是我获取百分比的方式,错误的进度是Else块中的ChunkProgress值: If Not ChunkIndex = Chu
Else
块中的ChunkProgress
值:
If Not ChunkIndex = ChunkCount Then
ProgressArguments =
New SplitProgressChangedArgs(
TotalProgress:=(TotalSize - SizeRemaining) * (100I / TotalSize),
ChunkProgress:=(100I / ChunkSize) * (SizeWritten - BufferLength),
ChunksToCreate:=ChunkCount + 1,
ChunksCreated:=ChunkIndex)
Else
ProgressArguments =
New SplitProgressChangedArgs(
TotalProgress:=(TotalSize - SizeRemaining) * (100I / TotalSize) - 1.0R,
ChunkProgress:=(100I / ChunkSize) * (SizeWritten - InputStream.Length),
ChunksToCreate:=ChunkCount + 1,
ChunksCreated:=ChunkIndex)
End If
TotalSize=被拆分文件的固定大小,以字节为单位(在本例中为6,74 gb)
ChunkSize=块的固定大小,以字节为单位(在本例中为1 GB)
SizeMaining=剩余的总大小计数器,以字节为单位(在本例中为6,74 gb到0)
SizeWrited=块大小写入计数器,以字节为单位(在本例中为0到1 GB)
有人能帮我在写最后一块时确定百分比吗
这是该类别的相关代码:
''' <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>
''' Splits the specified file.
''' </summary>
''' <param name="InputFile">Indicates the file to split.</param>
''' <param name="ChunkSize">Indicates the size of each chunk.</param>
''' <param name="ChunkName">Indicates the name-format for the chunks.</param>
''' <param name="ChunkExt">Indicates the file-extension for the chunks.</param>
''' <param name="Overwrite">
''' If set to <c>true</c> any existing file will be overwritten if needed to create a chunk,
''' otherwise, an exception will be thrown.
''' </param>
''' <param name="DeleteAfterSplit">If set to <c>true</c> the input file will be deleted after a successful split.</param>
''' <exception cref="System.OverflowException">'ChunkSize' should be smaller than the Filesize.</exception>
''' <exception cref="System.IO.IOException">File already exist</exception>
Public Sub Split(ByVal InputFile As String,
ByVal ChunkSize As Long,
Optional ByVal ChunkName As String = Nothing,
Optional ByVal ChunkExt As String = Nothing,
Optional ByVal Overwrite As Boolean = False,
Optional ByVal DeleteAfterSplit As Boolean = False)
' The progress event arguments.
Dim ProgressArguments As SplitProgressChangedArgs
' FileInfo instance of the input file.
Dim fInfo As New FileInfo(InputFile)
' The total filesize to split, in bytes.
Dim TotalSize As Long = fInfo.Length
' 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 write the chunks.
Dim Buffer As Byte() = New Byte() {}
' The buffer length.
Dim BufferLength As Integer = Me.BufferSize
' The total amount of chunks to create.
Dim ChunkCount As Integer = CInt(Math.Floor(fInfo.Length / ChunkSize))
' Keeps track of the current chunk.
Dim ChunkIndex As Integer = 0I
' A zero-filled string to enumerate the chunk files.
Dim Zeros As String = String.Empty
' The given filename for each chunk.
Dim ChunkFile As String = String.Empty
' The chunk file basename.
ChunkName = If(String.IsNullOrEmpty(ChunkName),
Path.Combine(fInfo.DirectoryName, Path.GetFileNameWithoutExtension(fInfo.Name)),
Path.Combine(fInfo.DirectoryName, ChunkName))
' The chunk file extension.
ChunkExt = If(String.IsNullOrEmpty(ChunkExt),
fInfo.Extension.Substring(1I),
ChunkExt)
' If ChunkSize is bigger than filesize then...
If ChunkSize >= fInfo.Length Then
Throw New OverflowException("'ChunkSize' should be smaller than the Filesize.")
Exit Sub
' For cases where a chunksize is smaller than the buffersize.
ElseIf ChunkSize < BufferLength Then
BufferLength = CInt(ChunkSize)
End If ' ChunkSize <>...
' If not file-overwrite is allowed then...
If Not Overwrite Then
For Index As Integer = 0I To (ChunkCount)
' Set chunk filename.
Zeros = New String("0", CStr(ChunkCount).Length - CStr(Index + 1I).Length)
ChunkFile = String.Format("{0}.{1}.{2}", ChunkName, Zeros & CStr(Index + 1I), ChunkExt)
' If chunk file already exists then...
If File.Exists(ChunkFile) Then
Throw New IOException(String.Format("File already exist: {0}", ChunkFile))
Exit Sub
End If ' File.Exists(ChunkFile)
Next Index
Zeros = String.Empty
ChunkFile = String.Empty
End If ' Overwrite
' Open the file to start reading bytes.
Using InputStream As New FileStream(fInfo.FullName, FileMode.Open)
Using BinaryReader As New BinaryReader(InputStream)
While (InputStream.Position < InputStream.Length)
' Set chunk filename.
Zeros = New String("0", CStr(ChunkCount).Length - CStr(ChunkIndex + 1I).Length)
ChunkFile = String.Format("{0}.{1}.{2}", ChunkName, Zeros & CStr(ChunkIndex + 1I), ChunkExt)
' Reset written byte-length counter.
SizeWritten = 0L
' Create the chunk file to Write the bytes.
Using OutputStream As New FileStream(ChunkFile, FileMode.Create)
Using BinaryWriter As New BinaryWriter(OutputStream)
' Read until reached the end-bytes of the input file.
While (SizeWritten < ChunkSize) AndAlso (InputStream.Position < InputStream.Length)
' Read bytes from the original file (BufferSize byte-length).
Buffer = BinaryReader.ReadBytes(BufferLength)
' Write those bytes in the chunk file.
BinaryWriter.Write(Buffer)
' Increment the bytes-written counter.
SizeWritten += Buffer.Count
' Decrease the bytes-remaining counter.
SizeRemaining -= Buffer.Count
If Not ChunkIndex = ChunkCount Then
ProgressArguments =
New SplitProgressChangedArgs(
TotalProgress:=(TotalSize - SizeRemaining) * (100I / TotalSize),
ChunkProgress:=(100I / ChunkSize) * (SizeWritten - BufferLength),
ChunksToCreate:=ChunkCount + 1,
ChunksCreated:=ChunkIndex)
Else
ProgressArguments =
New SplitProgressChangedArgs(
TotalProgress:=(TotalSize - SizeRemaining) * (100I / TotalSize) - 1.0R,
ChunkProgress:=(100I / ChunkSize) * (SizeWritten - InputStream.Length),
ChunksToCreate:=ChunkCount + 1,
ChunksCreated:=ChunkIndex)
End If
' Report the progress.
RaiseEvent SplitProgressChanged(Me, ProgressArguments)
End While ' (SizeWritten < ChunkSize) AndAlso (InputStream.Position < InputStream.Length)
OutputStream.Flush()
End Using ' BinaryWriter
End Using ' OutputStream
ChunkIndex += 1I 'Increment the chunk file counter.
End While ' InputStream.Position < InputStream.Length
End Using ' BinaryReader
End Using ' InputStream
End Sub
进度不能正确显示在最后一个块上的原因是,您正在根据“正常”块大小计算进度 例如(使用简化值): 如果最后一个块只有750个字节,我们必须通过除以
(thisChunk/ChunkSize)
进行更正:
对于Else
案例,请尝试此操作(InputStream.Length-sizewrited)
应获取剩余块的大小:
ProgressArguments =
New SplitProgressChangedArgs(
TotalProgress:=(TotalSize - SizeRemaining) * (100I / TotalSize) - 1.0R,
ChunkProgress:=(100I / ChunkSize) * (SizeWritten - InputStream.Length) / ((InputStream.Length - SizeWritten) / ChunkSize),
ChunksToCreate:=ChunkCount + 1,
ChunksCreated:=ChunkIndex)
感谢您的帮助,但值始终为“-100”,我试图注意到您提供的操作中有什么问题,但我找不到问题所在。请注意:“inputstream.length”的值与“TotalSize”的值(在本例中为6,74 gb)相同,可能这就是问题所在,因为我无法(或不知道如何)获取最后一个块的大小,可能这是必要的因素。这是获取最后一个大小块(750 mb)的计算:(inputstream.length-(ChunkSize*ChunkIndex))完成:(100I/(InputStream.Length-(ChunkSize*ChunkIndex))*(sizewrited-BufferLength)这就是您现在期望的输出吗?没问题。我会找你的新问题,看看能不能帮你一把。
500 out of 1000 bytes with ChunkSize = 1000
500 / ChunkSize = %
500/1000 = 0.5
500 out of 750 bytes with ChunkSize = 1000
500 / ChunkSize / (thisChunk / ChunkSize) = %
500/1000 / (750/1000) = 0.667
ProgressArguments =
New SplitProgressChangedArgs(
TotalProgress:=(TotalSize - SizeRemaining) * (100I / TotalSize) - 1.0R,
ChunkProgress:=(100I / ChunkSize) * (SizeWritten - InputStream.Length) / ((InputStream.Length - SizeWritten) / ChunkSize),
ChunksToCreate:=ChunkCount + 1,
ChunksCreated:=ChunkIndex)