使用带有进度报告的C#提取ZipFile
有人能告诉我,是否有可能(并给出一个例子,如果有),如何让进度条(和状态标签,如果可能的话)显示正在使用“ZipFile”(Ionic.ZIP,)提取的ZIP文件的进度 我的WinForm在将ZIP文件从我选择的路径提取到一个新路径方面做得很好,使用文本框和浏览按钮以及所有的jazz都不用担心。。。然而,唯一的问题是,在这段时间里,我不能在我的表单上使用任何东西,就好像它已经冻结了一样,但这只是因为它在后台解压了ZIP文件 ZIP文件是一个很大的文件,我想通过添加一个进度条来显示解压是如何进行的,并且有一个准确的ETA,从而减少对正在发生的事情的混淆 当然这是可能的,我只是不知道如何在C#WinForms中实现这一点,我已经在网络上进行了相当不错的浏览,但没有真正找到适合我的示例 下面是一个粗略的例子:使用带有进度报告的C#提取ZipFile,c#,winforms,C#,Winforms,有人能告诉我,是否有可能(并给出一个例子,如果有),如何让进度条(和状态标签,如果可能的话)显示正在使用“ZipFile”(Ionic.ZIP,)提取的ZIP文件的进度 我的WinForm在将ZIP文件从我选择的路径提取到一个新路径方面做得很好,使用文本框和浏览按钮以及所有的jazz都不用担心。。。然而,唯一的问题是,在这段时间里,我不能在我的表单上使用任何东西,就好像它已经冻结了一样,但这只是因为它在后台解压了ZIP文件 ZIP文件是一个很大的文件,我想通过添加一个进度条来显示解压是如何进行的
private void button1_Click(object sender, EventArgs e)
{
var ROBOT0007 = textBox1.Text + @"\" + "ROBOT0007"; //ROBOT0007 folder
var ROBOT_INSTALL = textBox1.Text + @"\" + "911" + @"\" + "files"; //ROBOT0007/911/files
var ROBOT_INSTALL_SPECIAL = ROBOT_INSTALL + @"\" + "special.rar"; //ROBOT0007/911/files/special.rar
//If the path has text...
if (textBox1.TextLength > 0)
{
//if the subfolder doesn't exist then make it.
if (!Directory.Exists(ROBOT0007))
{
Directory.CreateDirectory(ROBOT0007);
}
//if the textbox directory exists
if (Directory.Exists(ROBOT0007))
{
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}
}
}
}
更新(2014年11月4日):我已经删除了文本框,现在回到简单的基础,下面的工作与背景工人,但取消按钮没有对RAR文件的影响。。。有什么建议吗
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Text;
using System.Windows.Forms;
using Ionic.Zip;
using System.IO;
namespace BackgroundWorkerSample
{
// The BackgroundWorker will be used to perform a long running action
// on a background thread. This allows the UI to be free for painting
// as well as other actions the user may want to perform. The background
// thread will use the ReportProgress event to update the ProgressBar
// on the UI thread.
public partial class Form1 : Form
{
/// <summary>
/// The backgroundworker object on which the time consuming operation
/// shall be executed
/// </summary>
BackgroundWorker backgroundWorker1;
public Form1()
{
InitializeComponent();
backgroundWorker1 = new BackgroundWorker();
// Create a background worker thread that ReportsProgress &
// SupportsCancellation
// Hook up the appropriate events.
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler
(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
/// <summary>
/// On completed do the appropriate task
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// The background process is complete. We need to inspect
// our response to see if an error occurred, a cancel was
// requested or if we completed successfully.
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
// Check to see if an error occurred in the background process.
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
// Everything completed normally.
lblStatus.Text = "Task Completed...";
}
//Change the status of the buttons on the UI accordingly
btnStart.Enabled = true;
btnCancel.Enabled = false;
}
/// <summary>
/// Notification is performed here to the progress bar
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// This function fires on the UI thread so it's safe to edit
// the UI control directly, no funny business with Control.Invoke :)
// Update the progressBar with the integer supplied to us from the
// ReportProgress() function.
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
}
/// <summary>
/// Time consuming operations go here </br>
/// i.e. Database operations,Reporting
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// The sender is the BackgroundWorker object we need it to
// report progress and check for cancellation.
//NOTE : Never play with the UI thread here...
for (int i = 0; i < 100; i++)
{
//Thread.Sleep(100);
string INSTALL_FOLDER= "C:" + @"\" + "Program Files (x86)" + @"\" + "Robot91111"+ @"\" + "basic" + @"\" + "string" + @"\" + "special.rar";
string BURGOS_FOLDER = "C:" + @"\" + "Program Files (x86)" + @"\" + "Robot91111" + @"\" + "Burgos_Folder";
if (!Directory.Exists(BURGOS_FOLDER))
{
Directory.CreateDirectory(BURGOS_FOLDER);
using (ZipFile zip = ZipFile.Read(INSTALL_FOLDER))
{
zip.ExtractAll(BURGOS_FOLDER, ExtractExistingFileAction.OverwriteSilently);
}
}
// Periodically report progress to the main thread so that it can
// update the UI. In most cases you'll just need to send an
// integer that will update a ProgressBar
backgroundWorker1.ReportProgress(i);
// Periodically check if a cancellation request is pending.
// If the user clicks cancel the line
// m_AsyncWorker.CancelAsync(); if ran above. This
// sets the CancellationPending to true.
// You must check this flag in here and react to it.
// We react to it by setting e.Cancel to true and leaving
if (backgroundWorker1.CancellationPending)
{
// Set the e.Cancel flag so that the WorkerCompleted event
// knows that the process was cancelled.
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
}
//Report 100% completion on operation completed
backgroundWorker1.ReportProgress(100);
}
private void btnStartAsyncOperation_Click(object sender, EventArgs e)
{
//Change the status of the buttons on the UI accordingly
//The start button is disabled as soon as the background operation is started
//The Cancel button is enabled so that the user can stop the operation
//at any point of time during the execution
btnStart.Enabled = false;
btnCancel.Enabled = true;
// Kickoff the worker thread to begin it's DoWork function.
backgroundWorker1.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
// Notify the worker thread that a cancel has been requested.
// The cancel will not actually happen until the thread in the
// DoWork checks the backgroundWorker1.CancellationPending flag.
backgroundWorker1.CancelAsync();
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用系统线程;
使用系统文本;
使用System.Windows.Forms;
使用Ionic.Zip;
使用System.IO;
命名空间BackgroundWorkerSample
{
//BackgroundWorker将用于执行长时间运行的操作
//在后台线程上。这允许用户界面自由绘制
//以及用户可能要执行的其他操作。后台
//线程将使用ReportProgress事件更新ProgressBar
//在UI线程上。
公共部分类Form1:Form
{
///
///对其执行耗时操作的backgroundworker对象
///执行
///
背景工人背景工人1;
公共表格1()
{
初始化组件();
backgroundWorker1=新的BackgroundWorker();
//创建报告进程的后台工作线程&
//支撑扫描细胞
//连接适当的事件。
backgroundWorker1.DoWork+=新的DoWorkerVenthandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged+=新的ProgressChangedEventHandler
(背景工作1_进度变更);
backgroundWorker1.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler
(后台工作1_运行工作完成);
backgroundWorker1.WorkerReportsProgress=true;
backgroundWorker1.WorkerSupportsScanCellation=true;
}
///
///完成后,执行适当的任务
///
///
///
void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
//后台程序已经完成,我们需要检查
//我们的响应是查看是否发生了错误,取消了
//请求或如果我们成功完成。
如果(如已取消)
{
lblStatus.Text=“任务已取消。”;
}
//检查后台进程中是否发生错误。
否则如果(例如错误!=null)
{
lblStatus.Text=“执行后台操作时出错。”;
}
其他的
{
//一切正常完成。
lblStatus.Text=“任务已完成…”;
}
//相应地更改UI上按钮的状态
btnStart.Enabled=true;
btnCancel.Enabled=false;
}
///
///在此处向进度条执行通知
///
///
///
void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
//此函数在UI线程上激发,因此可以安全地进行编辑
//直接使用UI控件,与控件没有任何有趣的业务。调用:)
//使用从提供给我们的整数更新progressBar
//ReportProgress()函数。
progressBar1.值=e.ProgressPercentage;
lblStatus.Text=“处理……”+progressBar1.Value.ToString()+“%”;
}
///
///耗时的操作在这里进行
///即数据库操作、报告
///
///
///
无效backgroundWorker1\u DoWork(对象发送方,DoWorkerVentargs e)
{
//发送方是我们需要的BackgroundWorker对象
//报告进度并检查取消情况。
//注意:永远不要在这里玩UI线程。。。
对于(int i=0;i<100;i++)
{
//睡眠(100);
string INSTALL\u FOLDER=“C:”+@“\”+”程序文件(x86)”+@“\”+”机器人91111“+@“\”+”基本“+@“\”+”字符串“+@“\”+”特殊.rar”;
string BURGOS_FOLDER=“C:”++“\”+“程序文件(x86)”++“\”+“机器人91111”++“\”+“BURGOS_文件夹”;
如果(!Directory.Exists(BURGOS_文件夹))
{
CreateDirectory(BURGOS_文件夹);
使用(ZipFile zip=ZipFile.Read(安装文件夹))
{
ExtractAll(BURGOS_文件夹,ExtractExistingFileAction.OverwriteSilently);
}
}
//定期向主线程报告进度,以便它能够
//更新用户界面。在大多数情况下,您只需发送
//将更新进度条的整数
幕后工作者
/*...*/
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
zip.ExtractProgress +=
new EventHandler<ExtractProgressEventArgs>(zip_ExtractProgress);
zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}
/*...*/
void zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
{
if (e.TotalBytesToTransfer > 0)
{
progressBar1.Value = Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer);
}
}
private int totalFiles;
private int filesExtracted;
/*...*/
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
totalFiles = zip.Count;
filesExtracted = 0;
zip.ExtractProgress += ZipExtractProgress;
zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}
/*...*/
private void ZipExtractProgress(object sender, ExtractProgressEventArgs e)
{
if (e.EventType != ZipProgressEventType.Extracting_BeforeExtractEntry)
return;
filesExtracted++;
progressBar.Value = 100 * filesExtracted / totalFiles;
}
using System.IO.Compression;
private async void Unzip(string filePath)
{
var _downloadPath = configuration.GetValue("DownloadPath");
var _extractPath = configuration.GetValue("ExtractPath");
var _extractPattern = configuration.GetValue("ExtractPattern");
Console.WriteLine($"Удаление старых файлов из директории: '{_extractPath}'");
var directoryInfo = new DirectoryInfo(_extractPath);
foreach (var file in directoryInfo.GetFiles())
{
file.Delete();
}
Console.WriteLine($"Распаковка файла: '{filePath}'");
var regex = new Regex(_extractPattern);
var fileList = new List();
var totalFiles = 0;
var filesExtracted = 0;
using (var archive = await Task.Run(() => ZipFile.OpenRead(filePath)))
{
foreach (var file in archive.Entries)
{
if (regex.IsMatch(file.Name))
{
fileList.Add(file);
totalFiles++;
}
}
foreach (var file in fileList)
{
Console.WriteLine($"Извлечение файла: '{file.Name}'");
await Task.Run(() =>
{
file.ExtractToFile($"{_extractPath}{file.Name}");
filesExtracted++;
var progress = Convert.ToInt32(100 * filesExtracted / totalFiles);
Console.WriteLine($"Извлечено: {progress}%");
});
}
}
}
appsettings.json example
{
"DownloadPath": "f:\\download\\",
"ExtractPath": "f:\\download\\extract\\",
"ExtractPattern": "ACTSTAT.DBF|CENTERST.DBF|CURENTST.DBF|ESTSTAT.DBF|FLATTYPE.DBF|NDOCTYPE.DBF|OPERSTAT.DBF|ROOMTYPE.DBF|SOCRBASE.DBF|STRSTAT.DBF|[A-Z]{1}16.DBF",
}