我正在编写一个复制文件的程序。我有正确的文件复制,进度条更新,但我收到一个错误,指出e.ProgressPercentage是101. bgWorker_ProgressChanged事件处理程序的代码是:
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// We will increase the progress bar when work progress is reported.
pbCopyProgress.Maximum = 100;
pbCopyProgress.Value = e.ProgressPercentage;
}
以下是bgWorker_DoWork事件处理程序的代码:
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Gets the size of the file in bytes.
Int64 iSize = strInputFile.Length;
// Keeps track of the total bytes downloaded so we can update the progress bar.
Int64 iRunningByteTotal = 0;
// Open the input file for reading.
using (FileStream InputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
// Using the FileStream object, we can write the output file.
using (FileStream OutputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
// Loop the stream and get the file into the byte buffer.
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = InputFile.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
// Calculate the progress out of a base "100."
double dIndex;
double dTotal;
double dProgressPercentage;
// Write the bytes to the file system at the file path specified.
dIndex = (double)(iRunningByteTotal);
dTotal = (double)byteBuffer.Length;
dProgressPercentage = (dIndex / dTotal);
OutputFile.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
intProgress = Convert.ToUInt16(dProgressPercentage);
// Update the progress bar.
bgWorker.ReportProgress(intProgress);
}
// Close the output file.
OutputFile.Close();
}
// Close the input file.
InputFile.Close();
}
}
正如我所说,进度条正在更新,但是我收到错误,因为它似乎在文件达到100%后继续复制。如果我在bgWorker.ReportProgress(intProgress)行之后立即放入MessageBox.Show(Convert.ToString(intProgress)),对话框将弹出101文本。任何帮助将不胜感激。
答案 0 :(得分:9)
您将运行总计除以块缓冲区的长度,而不是整个流,这意味着结果基本上是无限制的。你也没有乘以100,但这个问题被比率增长大于1的事实掩盖了。
但是你看起来非常困难 - 你想要的代码就是:
bgWorker.ReportProgress((int)(100 * runningByteTotal / fileLength))
你应该在循环开始之前设置fileLength(它需要是文件的长度,而不是文件名,正如@azyberezovsky在他的回答中指出的那样)。
您可以使用简单的整数运算来进行此计算,而不是需要浮点类型,只要在除法之前乘以100即可。
作为一个风格点,你不需要在变量名前面的所有'我和's' - 这不被认为是好的C#风格。变量通常也不是以大写字母开头的 - 如果没有别的话,那就会混淆SO代码语法高亮显示......
答案 1 :(得分:1)
这不是文件大小 - 它只是文件名字符串的长度:
Int64 iSize = strInputFile.Length;
这也不是文件大小,这是用于将数据写入输出文件的缓冲区大小:
dTotal = (double)byteBuffer.Length;
您需要的是
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
using (FileStream inputFile = new FileStream(strInputFile, FileMode.Open, FileAccess.Read, FileShare.None))
using (FileStream outputFile = new FileStream(strOutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
long totalBytesToWrite = inputFile.Length;
long totalBytesWritten = 0;
byte[] buffer = new byte[512]; // provide any buffer size here
int bytesToWrite;
ushort percentage;
while ((bytesToWrite = inputFile.Read(buffer, 0, buffer.Length)) > 0)
{
outputFile.Write(buffer, 0, bytesToWrite);
totalBytesWritten += bytesToWrite;
percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
bgWorker.ReportProgress(percentage);
}
}
}
请记住 - 如果您使用using
块,则无需手动关闭流 - 此块将在此块的末尾处理(即关闭)。
答案 2 :(得分:0)
声明最大值:
pbCopyProgress.Maximum = InputFile.Read(byteBuffer, 0, byteBuffer.Length)
删除行:
percentage = (ushort)((100 * totalBytesWritten)/totalBytesToWrite);
来自bgWorker_DoWork
,并在bgWorker_DoWork
中循环之前声明计数器。例如:
int counter = 1;
在关闭括号之前递增计数器(counter++
);
在bgWorker_ProgressChanged
中更新百分比:
pbCopyProgress.Value = e.ProgressPercentage;
如果您想填写任何带有文字的标签,显示下一行计算百分比的百分比:
int percent = 100 / (byteBuffer.Length / e.ProgressPercentage);
Label1.Text = String.Format("Passed: {0} %, percent.ToString());
这些行也应该在bgWorker_ProgressChanged
。