C# 文件压缩工具(支持 ZIP 打包)

C# 文件压缩解决方案,支持将多个文件打包成一个 ZIP 文件,包含密码保护、压缩级别控制、进度监控等功能。


一、项目结构

FileCompressor/
├── Program.cs                 # 程序入口
├── MainForm.cs                # 主窗体
├── ZipManager.cs              # ZIP压缩管理器
├── CompressionProgress.cs     # 压缩进度监控
├── FileSelector.cs           # 文件选择器
├── ZipExtractor.cs           # ZIP解压管理器
└── FileCompressor.csproj

二、核心源码实现

2.1 项目文件 (FileCompressor.csproj)

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
  </PropertyGroup>

  <ItemGroup>
    <!-- 使用 .NET 内置的压缩库 -->
    <PackageReference Include="System.IO.Compression" Version="4.3.0" />
    <PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
    
    <!-- 可选:使用 SharpZipLib 获得更多功能 -->
    <PackageReference Include="SharpZipLib" Version="1.4.2" />
  </ItemGroup>

</Project>

2.2 程序入口 (Program.cs)

using System;
using System.Windows.Forms;

namespace FileCompressor
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
}

2.3 主窗体 (MainForm.cs)

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace FileCompressor
{
    public partial class MainForm : Form
    {
        private ZipManager zipManager = new ZipManager();
        private FileSelector fileSelector = new FileSelector();
        private List<string> selectedFiles = new List<string>();
        private string outputZipPath = "";

        public MainForm()
        {
            InitializeComponent();
            zipManager.ProgressChanged += ZipManager_ProgressChanged;
            zipManager.OperationCompleted += ZipManager_OperationCompleted;
        }

        private void btnSelectFiles_Click(object sender, EventArgs e)
        {
            selectedFiles = fileSelector.SelectFiles();
            UpdateFileList();
        }

        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            selectedFiles = fileSelector.SelectFolder();
            UpdateFileList();
        }

        private void UpdateFileList()
        {
            lstFiles.Items.Clear();
            foreach (var file in selectedFiles)
            {
                lstFiles.Items.Add(Path.GetFileName(file));
            }
            
            lblFileCount.Text = $"已选择 {selectedFiles.Count} 个文件";
            UpdateTotalSize();
        }

        private void UpdateTotalSize()
        {
            long totalSize = 0;
            foreach (var file in selectedFiles)
            {
                if (File.Exists(file))
                {
                    totalSize += new FileInfo(file).Length;
                }
            }
            
            lblTotalSize.Text = $"总大小: {FormatFileSize(totalSize)}";
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        private void btnSelectOutput_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "ZIP文件|*.zip|所有文件|*.*";
            saveFileDialog.DefaultExt = "zip";
            saveFileDialog.FileName = "archive.zip";
            
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                outputZipPath = saveFileDialog.FileName;
                txtOutputPath.Text = outputZipPath;
            }
        }

        private void btnCompress_Click(object sender, EventArgs e)
        {
            if (selectedFiles.Count == 0)
            {
                MessageBox.Show("请先选择要压缩的文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (string.IsNullOrEmpty(outputZipPath))
            {
                MessageBox.Show("请选择输出文件路径!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            // 检查输出文件是否已存在
            if (File.Exists(outputZipPath) && !chkOverwrite.Checked)
            {
                MessageBox.Show("输出文件已存在,请勾选覆盖选项或选择其他文件名!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            // 禁用按钮
            btnCompress.Enabled = false;
            btnCancel.Enabled = true;
            progressBar.Visible = true;
            lblProgress.Text = "正在压缩...";

            // 获取压缩设置
            var settings = new ZipSettings
            {
                OutputPath = outputZipPath,
                CompressionLevel = GetCompressionLevel(),
                Password = txtPassword.Text,
                IncludeBaseDirectory = chkIncludeBaseDir.Checked,
                OverwriteExisting = chkOverwrite.Checked
            };

            // 开始压缩
            zipManager.CompressFiles(selectedFiles, settings);
        }

        private System.IO.Compression.CompressionLevel GetCompressionLevel()
        {
            switch (cmbCompressionLevel.SelectedIndex)
            {
                case 0: return System.IO.Compression.CompressionLevel.NoCompression;
                case 1: return System.IO.Compression.CompressionLevel.Fastest;
                case 2: return System.IO.Compression.CompressionLevel.Optimal;
                default: return System.IO.Compression.CompressionLevel.Optimal;
            }
        }

        private void ZipManager_ProgressChanged(object sender, ProgressEventArgs e)
        {
            // 更新进度条
            progressBar.Value = e.ProgressPercentage;
            lblProgress.Text = $"正在压缩: {e.CurrentFile} ({e.ProgressPercentage}%)";
            
            // 更新UI
            Application.DoEvents();
        }

        private void ZipManager_OperationCompleted(object sender, OperationCompletedEventArgs e)
        {
            // 启用按钮
            btnCompress.Enabled = true;
            btnCancel.Enabled = false;
            progressBar.Visible = false;

            if (e.Success)
            {
                lblProgress.Text = $"压缩完成!输出文件: {e.OutputPath}";
                MessageBox.Show($"压缩完成!\n输出文件: {e.OutputPath}\n压缩前大小: {FormatFileSize(e.OriginalSize)}\n压缩后大小: {FormatFileSize(e.CompressedSize)}\n压缩率: {e.CompressionRatio:P2}", 
                    "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                lblProgress.Text = $"压缩失败: {e.ErrorMessage}";
                MessageBox.Show($"压缩失败: {e.ErrorMessage}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            zipManager.CancelOperation();
            btnCancel.Enabled = false;
            lblProgress.Text = "操作已取消";
        }

        private void btnExtract_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "ZIP文件|*.zip|所有文件|*.*";
            
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                FolderBrowserDialog folderDialog = new FolderBrowserDialog();
                folderDialog.Description = "选择解压目标文件夹";
                
                if (folderDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        ZipExtractor extractor = new ZipExtractor();
                        extractor.ExtractZip(openFileDialog.FileName, folderDialog.SelectedPath, txtPassword.Text);
                        MessageBox.Show("解压完成!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"解压失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }

        #region Windows Form Designer generated code

        private System.ComponentModel.IContainer components = null;
        private MenuStrip menuStrip1;
        private ToolStripMenuItem 文件ToolStripMenuItem;
        private ToolStripMenuItem 退出ToolStripMenuItem;
        private ToolStripMenuItem 帮助ToolStripMenuItem;
        private ToolStripMenuItem 关于ToolStripMenuItem;
        private GroupBox groupBox1;
        private Button btnSelectFiles;
        private Button btnSelectFolder;
        private ListBox lstFiles;
        private Label lblFileCount;
        private Label lblTotalSize;
        private GroupBox groupBox2;
        private TextBox txtOutputPath;
        private Button btnSelectOutput;
        private Label label1;
        private ComboBox cmbCompressionLevel;
        private Label label2;
        private CheckBox chkIncludeBaseDir;
        private CheckBox chkOverwrite;
        private TextBox txtPassword;
        private Label label3;
        private GroupBox groupBox3;
        private Button btnCompress;
        private Button btnCancel;
        private Button btnExtract;
        private ProgressBar progressBar;
        private Label lblProgress;

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
            this.文件ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.退出ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.帮助ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.关于ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.lblTotalSize = new System.Windows.Forms.Label();
            this.lblFileCount = new System.Windows.Forms.Label();
            this.lstFiles = new System.Windows.Forms.ListBox();
            this.btnSelectFolder = new System.Windows.Forms.Button();
            this.btnSelectFiles = new System.Windows.Forms.Button();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.txtPassword = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.chkOverwrite = new System.Windows.Forms.CheckBox();
            this.chkIncludeBaseDir = new System.Windows.Forms.CheckBox();
            this.label2 = new System.Windows.Forms.Label();
            this.cmbCompressionLevel = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.btnSelectOutput = new System.Windows.Forms.Button();
            this.txtOutputPath = new System.Windows.Forms.TextBox();
            this.groupBox3 = new System.Windows.Forms.GroupBox();
            this.btnExtract = new System.Windows.Forms.Button();
            this.btnCancel = new System.Windows.Forms.Button();
            this.btnCompress = new System.Windows.Forms.Button();
            this.progressBar = new System.Windows.Forms.ProgressBar();
            this.lblProgress = new System.Windows.Forms.Label();
            this.menuStrip1.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.groupBox3.SuspendLayout();
            this.SuspendLayout();
            
            // menuStrip1
            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.文件ToolStripMenuItem,
                this.帮助ToolStripMenuItem});
            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
            this.menuStrip1.Name = "menuStrip1";
            this.menuStrip1.Size = new System.Drawing.Size(700, 25);
            this.menuStrip1.TabIndex = 0;
            this.menuStrip1.Text = "menuStrip1";
            
            // 文件ToolStripMenuItem
            this.文件ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.退出ToolStripMenuItem});
            this.文件ToolStripMenuItem.Name = "文件ToolStripMenuItem";
            this.文件ToolStripMenuItem.Size = new System.Drawing.Size(44, 21);
            this.文件ToolStripMenuItem.Text = "文件";
            
            // 退出ToolStripMenuItem
            this.退出ToolStripMenuItem.Name = "退出ToolStripMenuItem";
            this.退出ToolStripMenuItem.Size = new System.Drawing.Size(93, 22);
            this.退出ToolStripMenuItem.Text = "退出";
            this.退出ToolStripMenuItem.Click += new System.EventHandler(this.退出ToolStripMenuItem_Click);
            
            // 帮助ToolStripMenuItem
            this.帮助ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
                this.关于ToolStripMenuItem});
            this.帮助ToolStripMenuItem.Name = "帮助ToolStripMenuItem";
            this.帮助ToolStripMenuItem.Size = new System.Drawing.Size(44, 21);
            this.帮助ToolStripMenuItem.Text = "帮助";
            
            // 关于ToolStripMenuItem
            this.关于ToolStripMenuItem.Name = "关于ToolStripMenuItem";
            this.关于ToolStripMenuItem.Size = new System.Drawing.Size(107, 22);
            this.关于ToolStripMenuItem.Text = "关于";
            this.关于ToolStripMenuItem.Click += new System.EventHandler(this.关于ToolStripMenuItem_Click);
            
            // groupBox1
            this.groupBox1.Controls.Add(this.lblTotalSize);
            this.groupBox1.Controls.Add(this.lblFileCount);
            this.groupBox1.Controls.Add(this.lstFiles);
            this.groupBox1.Controls.Add(this.btnSelectFolder);
            this.groupBox1.Controls.Add(this.btnSelectFiles);
            this.groupBox1.Location = new System.Drawing.Point(12, 30);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(300, 300);
            this.groupBox1.TabIndex = 1;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "选择文件";
            
            // lblTotalSize
            this.lblTotalSize.AutoSize = true;
            this.lblTotalSize.Location = new System.Drawing.Point(20, 265);
            this.lblTotalSize.Name = "lblTotalSize";
            this.lblTotalSize.Size = new System.Drawing.Size(67, 13);
            this.lblTotalSize.TabIndex = 4;
            this.lblTotalSize.Text = "总大小: 0 KB";
            
            // lblFileCount
            this.lblFileCount.AutoSize = true;
            this.lblFileCount.Location = new System.Drawing.Point(20, 245);
            this.lblFileCount.Name = "lblFileCount";
            this.lblFileCount.Size = new System.Drawing.Size(67, 13);
            this.lblFileCount.TabIndex = 3;
            this.lblFileCount.Text = "已选择 0 个文件";
            
            // lstFiles
            this.lstFiles.FormattingEnabled = true;
            this.lstFiles.Location = new System.Drawing.Point(20, 25);
            this.lstFiles.Name = "lstFiles";
            this.lstFiles.Size = new System.Drawing.Size(260, 212);
            this.lstFiles.TabIndex = 2;
            
            // btnSelectFolder
            this.btnSelectFolder.Location = new System.Drawing.Point(150, 275);
            this.btnSelectFolder.Name = "btnSelectFolder";
            this.btnSelectFolder.Size = new System.Drawing.Size(130, 25);
            this.btnSelectFolder.TabIndex = 1;
            this.btnSelectFolder.Text = "选择文件夹";
            this.btnSelectFolder.UseVisualStyleBackColor = true;
            this.btnSelectFolder.Click += new System.EventHandler(this.btnSelectFolder_Click);
            
            // btnSelectFiles
            this.btnSelectFiles.Location = new System.Drawing.Point(20, 275);
            this.btnSelectFiles.Name = "btnSelectFiles";
            this.btnSelectFiles.Size = new System.Drawing.Size(120, 25);
            this.btnSelectFiles.TabIndex = 0;
            this.btnSelectFiles.Text = "选择文件...";
            this.btnSelectFiles.UseVisualStyleBackColor = true;
            this.btnSelectFiles.Click += new System.EventHandler(this.btnSelectFiles_Click);
            
            // groupBox2
            this.groupBox2.Controls.Add(this.txtPassword);
            this.groupBox2.Controls.Add(this.label3);
            this.groupBox2.Controls.Add(this.chkOverwrite);
            this.groupBox2.Controls.Add(this.chkIncludeBaseDir);
            this.groupBox2.Controls.Add(this.label2);
            this.groupBox2.Controls.Add(this.cmbCompressionLevel);
            this.groupBox2.Controls.Add(this.label1);
            this.groupBox2.Controls.Add(this.btnSelectOutput);
            this.groupBox2.Controls.Add(this.txtOutputPath);
            this.groupBox2.Location = new System.Drawing.Point(320, 30);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(350, 200);
            this.groupBox2.TabIndex = 2;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "压缩设置";
            
            // txtPassword
            this.txtPassword.Location = new System.Drawing.Point(100, 155);
            this.txtPassword.Name = "txtPassword";
            this.txtPassword.PasswordChar = '*';
            this.txtPassword.Size = new System.Drawing.Size(230, 23);
            this.txtPassword.TabIndex = 9;
            
            // label3
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(20, 158);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(44, 13);
            this.label3.TabIndex = 8;
            this.label3.Text = "密码:";
            
            // chkOverwrite
            this.chkOverwrite.AutoSize = true;
            this.chkOverwrite.Location = new System.Drawing.Point(20, 125);
            this.chkOverwrite.Name = "chkOverwrite";
            this.chkOverwrite.Size = new System.Drawing.Size(96, 17);
            this.chkOverwrite.TabIndex = 7;
            this.chkOverwrite.Text = "覆盖已有文件";
            this.chkOverwrite.UseVisualStyleBackColor = true;
            
            // chkIncludeBaseDir
            this.chkIncludeBaseDir.AutoSize = true;
            this.chkIncludeBaseDir.Location = new System.Drawing.Point(20, 100);
            this.chkIncludeBaseDir.Name = "chkIncludeBaseDir";
            this.chkIncludeBaseDir.Size = new System.Drawing.Size(120, 17);
            this.chkIncludeBaseDir.TabIndex = 6;
            this.chkIncludeBaseDir.Text = "包含基目录名称";
            this.chkIncludeBaseDir.UseVisualStyleBackColor = true;
            
            // label2
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(20, 75);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(56, 13);
            this.label2.TabIndex = 5;
            this.label2.Text = "压缩级别:";
            
            // cmbCompressionLevel
            this.cmbCompressionLevel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cmbCompressionLevel.FormattingEnabled = true;
            this.cmbCompressionLevel.Items.AddRange(new object[] { "无压缩", "最快压缩", "最佳压缩" });
            this.cmbCompressionLevel.Location = new System.Drawing.Point(100, 72);
            this.cmbCompressionLevel.Name = "cmbCompressionLevel";
            this.cmbCompressionLevel.Size = new System.Drawing.Size(230, 23);
            this.cmbCompressionLevel.TabIndex = 4;
            this.cmbCompressionLevel.SelectedIndex = 2;
            
            // label1
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(20, 45);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(56, 13);
            this.label1.TabIndex = 3;
            this.label1.Text = "输出文件:";
            
            // btnSelectOutput
            this.btnSelectOutput.Location = new System.Drawing.Point(305, 40);
            this.btnSelectOutput.Name = "btnSelectOutput";
            this.btnSelectOutput.Size = new System.Drawing.Size(25, 23);
            this.btnSelectOutput.TabIndex = 2;
            this.btnSelectOutput.Text = "...";
            this.btnSelectOutput.UseVisualStyleBackColor = true;
            this.btnSelectOutput.Click += new System.EventHandler(this.btnSelectOutput_Click);
            
            // txtOutputPath
            this.txtOutputPath.Location = new System.Drawing.Point(100, 42);
            this.txtOutputPath.Name = "txtOutputPath";
            this.txtOutputPath.Size = new System.Drawing.Size(200, 23);
            this.txtOutputPath.TabIndex = 1;
            
            // groupBox3
            this.groupBox3.Controls.Add(this.btnExtract);
            this.groupBox3.Controls.Add(this.btnCancel);
            this.groupBox3.Controls.Add(this.btnCompress);
            this.groupBox3.Location = new System.Drawing.Point(320, 240);
            this.groupBox3.Name = "groupBox3";
            this.groupBox3.Size = new System.Drawing.Size(350, 90);
            this.groupBox3.TabIndex = 3;
            this.groupBox3.TabStop = false;
            this.groupBox3.Text = "操作";
            
            // btnExtract
            this.btnExtract.Location = new System.Drawing.Point(240, 35);
            this.btnExtract.Name = "btnExtract";
            this.btnExtract.Size = new System.Drawing.Size(90, 25);
            this.btnExtract.TabIndex = 2;
            this.btnExtract.Text = "解压ZIP";
            this.btnExtract.UseVisualStyleBackColor = true;
            this.btnExtract.Click += new System.EventHandler(this.btnExtract_Click);
            
            // btnCancel
            this.btnCancel.Location = new System.Drawing.Point(130, 35);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(90, 25);
            this.btnCancel.TabIndex = 1;
            this.btnCancel.Text = "取消";
            this.btnCancel.UseVisualStyleBackColor = true;
            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
            this.btnCancel.Enabled = false;
            
            // btnCompress
            this.btnCompress.Location = new System.Drawing.Point(20, 35);
            this.btnCompress.Name = "btnCompress";
            this.btnCompress.Size = new System.Drawing.Size(90, 25);
            this.btnCompress.TabIndex = 0;
            this.btnCompress.Text = "压缩";
            this.btnCompress.UseVisualStyleBackColor = true;
            this.btnCompress.Click += new System.EventHandler(this.btnCompress_Click);
            
            // progressBar
            this.progressBar.Location = new System.Drawing.Point(12, 340);
            this.progressBar.Name = "progressBar";
            this.progressBar.Size = new System.Drawing.Size(658, 23);
            this.progressBar.TabIndex = 4;
            this.progressBar.Visible = false;
            
            // lblProgress
            this.lblProgress.AutoSize = true;
            this.lblProgress.Location = new System.Drawing.Point(12, 370);
            this.lblProgress.Name = "lblProgress";
            this.lblProgress.Size = new System.Drawing.Size(44, 13);
            this.lblProgress.TabIndex = 5;
            this.lblProgress.Text = "就绪...";
            
            // MainForm
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(682, 392);
            this.Controls.Add(this.lblProgress);
            this.Controls.Add(this.progressBar);
            this.Controls.Add(this.groupBox3);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.menuStrip1);
            this.MainMenuStrip = this.menuStrip1;
            this.Name = "MainForm";
            this.Text = "文件压缩工具 - ZIP打包";
            this.menuStrip1.ResumeLayout(false);
            this.menuStrip1.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.groupBox3.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("文件压缩工具 v1.0\n\n支持将多个文件打包成ZIP压缩包\n© 2024 版权所有", "关于", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #endregion
    }
}

2.4 ZIP压缩管理器 (ZipManager.cs)

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Threading;
using System.Threading.Tasks;

namespace FileCompressor
{
    /// <summary>
    /// ZIP压缩管理器
    /// </summary>
    public class ZipManager
    {
        private CancellationTokenSource cancellationTokenSource;
        private bool isOperationCancelled = false;

        // 事件
        public event EventHandler<ProgressEventArgs> ProgressChanged;
        public event EventHandler<OperationCompletedEventArgs> OperationCompleted;

        /// <summary>
        /// 压缩多个文件到一个ZIP文件
        /// </summary>
        public async void CompressFiles(List<string> filePaths, ZipSettings settings)
        {
            cancellationTokenSource = new CancellationTokenSource();
            isOperationCancelled = false;

            try
            {
                // 检查输出文件是否已存在
                if (File.Exists(settings.OutputPath) && !settings.OverwriteExisting)
                {
                    OnOperationCompleted(false, settings.OutputPath, 0, 0, "输出文件已存在");
                    return;
                }

                // 确保输出目录存在
                string outputDir = Path.GetDirectoryName(settings.OutputPath);
                if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))
                {
                    Directory.CreateDirectory(outputDir);
                }

                // 计算总大小
                long totalSize = CalculateTotalSize(filePaths);
                long compressedSize = 0;
                int fileCount = filePaths.Count;
                int processedCount = 0;

                // 使用异步压缩
                await Task.Run(() =>
                {
                    using (FileStream zipFileStream = new FileStream(settings.OutputPath, FileMode.Create))
                    using (ZipArchive archive = new ZipArchive(zipFileStream, ZipArchiveMode.Create, true))
                    {
                        foreach (string filePath in filePaths)
                        {
                            if (isOperationCancelled)
                                break;

                            if (File.Exists(filePath))
                            {
                                try
                                {
                                    // 获取相对路径
                                    string entryName = GetEntryName(filePath, settings.IncludeBaseDirectory);
                                    
                                    // 创建ZIP条目
                                    ZipArchiveEntry entry = archive.CreateEntry(entryName, settings.CompressionLevel);
                                    
                                    // 写入文件内容
                                    using (FileStream originalFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                                    using (Stream entryStream = entry.Open())
                                    {
                                        byte[] buffer = new byte[4096];
                                        int bytesRead;
                                        long fileSize = originalFileStream.Length;
                                        long copiedBytes = 0;

                                        while ((bytesRead = originalFileStream.Read(buffer, 0, buffer.Length)) > 0)
                                        {
                                            if (isOperationCancelled)
                                                break;

                                            entryStream.Write(buffer, 0, bytesRead);
                                            copiedBytes += bytesRead;
                                            compressedSize += bytesRead;

                                            // 更新进度
                                            int progress = (int)((double)compressedSize / totalSize * 100);
                                            OnProgressChanged(progress, Path.GetFileName(filePath));
                                        }
                                    }

                                    processedCount++;
                                }
                                catch (Exception ex)
                                {
                                    throw new Exception($"压缩文件 {filePath} 失败: {ex.Message}");
                                }
                            }
                            else if (Directory.Exists(filePath))
                            {
                                // 压缩文件夹
                                CompressDirectory(filePath, archive, settings, ref compressedSize, totalSize);
                                processedCount++;
                            }
                        }
                    }
                }, cancellationTokenSource.Token);

                if (!isOperationCancelled)
                {
                    // 获取压缩后文件大小
                    FileInfo zipFileInfo = new FileInfo(settings.OutputPath);
                    long finalCompressedSize = zipFileInfo.Length;
                    
                    OnOperationCompleted(true, settings.OutputPath, totalSize, finalCompressedSize, "压缩完成");
                }
            }
            catch (OperationCanceledException)
            {
                OnOperationCompleted(false, settings.OutputPath, 0, 0, "操作已取消");
            }
            catch (Exception ex)
            {
                OnOperationCompleted(false, settings.OutputPath, 0, 0, ex.Message);
            }
        }

        /// <summary>
        /// 压缩文件夹
        /// </summary>
        private void CompressDirectory(string folderPath, ZipArchive archive, ZipSettings settings, ref long compressedSize, long totalSize)
        {
            string baseFolderName = settings.IncludeBaseDirectory ? Path.GetFileName(folderPath) : "";
            
            foreach (string filePath in Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories))
            {
                if (isOperationCancelled)
                    break;

                try
                {
                    string relativePath = GetRelativePath(folderPath, filePath);
                    if (!string.IsNullOrEmpty(baseFolderName))
                    {
                        relativePath = Path.Combine(baseFolderName, relativePath);
                    }

                    ZipArchiveEntry entry = archive.CreateEntry(relativePath, settings.CompressionLevel);
                    
                    using (FileStream originalFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    using (Stream entryStream = entry.Open())
                    {
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        
                        while ((bytesRead = originalFileStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            if (isOperationCancelled)
                                break;
                                
                            entryStream.Write(buffer, 0, bytesRead);
                            compressedSize += bytesRead;
                            
                            // 更新进度
                            int progress = (int)((double)compressedSize / totalSize * 100);
                            OnProgressChanged(progress, Path.GetFileName(filePath));
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception($"压缩文件夹 {filePath} 失败: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 计算总大小
        /// </summary>
        private long CalculateTotalSize(List<string> filePaths)
        {
            long totalSize = 0;
            
            foreach (string path in filePaths)
            {
                if (File.Exists(path))
                {
                    totalSize += new FileInfo(path).Length;
                }
                else if (Directory.Exists(path))
                {
                    totalSize += CalculateDirectorySize(path);
                }
            }
            
            return totalSize;
        }

        /// <summary>
        /// 计算文件夹大小
        /// </summary>
        private long CalculateDirectorySize(string folderPath)
        {
            long size = 0;
            
            foreach (string file in Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories))
            {
                if (File.Exists(file))
                {
                    size += new FileInfo(file).Length;
                }
            }
            
            return size;
        }

        /// <summary>
        /// 获取ZIP条目名称
        /// </summary>
        private string GetEntryName(string filePath, bool includeBaseDirectory)
        {
            if (includeBaseDirectory)
            {
                return Path.GetFileName(filePath);
            }
            else
            {
                return Path.GetFileName(filePath);
            }
        }

        /// <summary>
        /// 获取相对路径
        /// </summary>
        private string GetRelativePath(string basePath, string fullPath)
        {
            Uri baseUri = new Uri(basePath.EndsWith("\\") ? basePath : basePath + "\\");
            Uri fullUri = new Uri(fullPath);
            return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fullUri).ToString().Replace('/', Path.DirectorySeparatorChar));
        }

        /// <summary>
        /// 取消操作
        /// </summary>
        public void CancelOperation()
        {
            isOperationCancelled = true;
            cancellationTokenSource?.Cancel();
        }

        /// <summary>
        /// 触发进度变化事件
        /// </summary>
        protected virtual void OnProgressChanged(int progress, string currentFile)
        {
            ProgressChanged?.Invoke(this, new ProgressEventArgs(progress, currentFile));
        }

        /// <summary>
        /// 触发操作完成事件
        /// </summary>
        protected virtual void OnOperationCompleted(bool success, string outputPath, long originalSize, long compressedSize, string message)
        {
            OperationCompleted?.Invoke(this, new OperationCompletedEventArgs(success, outputPath, originalSize, compressedSize, message));
        }
    }

    /// <summary>
    /// ZIP压缩设置
    /// </summary>
    public class ZipSettings
    {
        public string OutputPath { get; set; } = "";
        public CompressionLevel CompressionLevel { get; set; } = CompressionLevel.Optimal;
        public string Password { get; set; } = "";
        public bool IncludeBaseDirectory { get; set; } = false;
        public bool OverwriteExisting { get; set; } = false;
    }

    /// <summary>
    /// 进度事件参数
    /// </summary>
    public class ProgressEventArgs : EventArgs
    {
        public int ProgressPercentage { get; set; }
        public string CurrentFile { get; set; }

        public ProgressEventArgs(int progress, string currentFile)
        {
            ProgressPercentage = progress;
            CurrentFile = currentFile;
        }
    }

    /// <summary>
    /// 操作完成事件参数
    /// </summary>
    public class OperationCompletedEventArgs : EventArgs
    {
        public bool Success { get; set; }
        public string OutputPath { get; set; }
        public long OriginalSize { get; set; }
        public long CompressedSize { get; set; }
        public string ErrorMessage { get; set; }

        public double CompressionRatio => OriginalSize > 0 ? 1.0 - (double)CompressedSize / OriginalSize : 0;

        public OperationCompletedEventArgs(bool success, string outputPath, long originalSize, long compressedSize, string errorMessage)
        {
            Success = success;
            OutputPath = outputPath;
            OriginalSize = originalSize;
            CompressedSize = compressedSize;
            ErrorMessage = errorMessage;
        }
    }
}

2.5 文件选择器 (FileSelector.cs)

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace FileCompressor
{
    /// <summary>
    /// 文件选择器
    /// </summary>
    public class FileSelector
    {
        /// <summary>
        /// 选择多个文件
        /// </summary>
        public List<string> SelectFiles()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Multiselect = true;
            openFileDialog.Filter = "所有文件|*.*|文本文件|*.txt|图片文件|*.jpg;*.png;*.gif;*.bmp|文档文件|*.doc;*.docx;*.pdf";
            openFileDialog.Title = "选择要压缩的文件";
            
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                return new List<string>(openFileDialog.FileNames);
            }
            
            return new List<string>();
        }

        /// <summary>
        /// 选择文件夹
        /// </summary>
        public List<string> SelectFolder()
        {
            FolderBrowserDialog folderDialog = new FolderBrowserDialog();
            folderDialog.Description = "选择要压缩的文件夹";
            folderDialog.ShowNewFolderButton = false;
            
            if (folderDialog.ShowDialog() == DialogResult.OK)
            {
                return new List<string> { folderDialog.SelectedPath };
            }
            
            return new List<string>();
        }

        /// <summary>
        /// 选择多个文件夹
        /// </summary>
        public List<string> SelectMultipleFolders()
        {
            List<string> folders = new List<string>();
            
            while (true)
            {
                FolderBrowserDialog folderDialog = new FolderBrowserDialog();
                folderDialog.Description = "选择要压缩的文件夹(点击取消结束选择)";
                folderDialog.ShowNewFolderButton = false;
                
                if (folderDialog.ShowDialog() == DialogResult.OK)
                {
                    folders.Add(folderDialog.SelectedPath);
                    
                    DialogResult result = MessageBox.Show("是否继续选择其他文件夹?", "选择文件夹", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (result == DialogResult.No)
                        break;
                }
                else
                {
                    break;
                }
            }
            
            return folders;
        }
    }
}

2.6 ZIP解压管理器 (ZipExtractor.cs)

using System;
using System.IO;
using System.IO.Compression;

namespace FileCompressor
{
    /// <summary>
    /// ZIP解压管理器
    /// </summary>
    public class ZipExtractor
    {
        /// <summary>
        /// 解压ZIP文件
        /// </summary>
        public void ExtractZip(string zipPath, string extractPath, string password = "")
        {
            try
            {
                // 确保解压目录存在
                if (!Directory.Exists(extractPath))
                {
                    Directory.CreateDirectory(extractPath);
                }

                // 使用 .NET 内置的 ZIP 解压功能
                ZipFile.ExtractToDirectory(zipPath, extractPath, true);
            }
            catch (Exception ex)
            {
                throw new Exception($"解压失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 解压ZIP文件中的特定文件
        /// </summary>
        public void ExtractSpecificFiles(string zipPath, string extractPath, string[] filePatterns)
        {
            try
            {
                if (!Directory.Exists(extractPath))
                {
                    Directory.CreateDirectory(extractPath);
                }

                using (ZipArchive archive = ZipFile.OpenRead(zipPath))
                {
                    foreach (string pattern in filePatterns)
                    {
                        var entries = archive.Entries.Where(e => e.Name.Contains(pattern, StringComparison.OrdinalIgnoreCase));
                        
                        foreach (var entry in entries)
                        {
                            string destinationPath = Path.Combine(extractPath, entry.Name);
                            entry.ExtractToFile(destinationPath, true);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"解压特定文件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取ZIP文件中的文件列表
        /// </summary>
        public string[] GetFileList(string zipPath)
        {
            try
            {
                using (ZipArchive archive = ZipFile.OpenRead(zipPath))
                {
                    string[] files = new string[archive.Entries.Count];
                    for (int i = 0; i < archive.Entries.Count; i++)
                    {
                        files[i] = archive.Entries[i].FullName;
                    }
                    return files;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"获取文件列表失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 检查ZIP文件是否有效
        /// </summary>
        public bool IsValidZipFile(string zipPath)
        {
            try
            {
                using (ZipArchive archive = ZipFile.OpenRead(zipPath))
                {
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }
    }
}

2.7 使用 SharpZipLib 的增强版本(支持密码保护)

// 如果需要更强的密码保护和更多功能,可以使用 SharpZipLib
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;

namespace FileCompressor
{
    /// <summary>
    /// 使用 SharpZipLib 的 ZIP 压缩管理器(支持密码保护)
    /// </summary>
    public class AdvancedZipManager
    {
        /// <summary>
        /// 压缩文件(支持密码)
        /// </summary>
        public void CompressFilesWithPassword(List<string> filePaths, string outputPath, string password, int compressionLevel = 3)
        {
            try
            {
                using (FileStream fsOut = File.Create(outputPath))
                using (ZipOutputStream zipStream = new ZipOutputStream(fsOut))
                {
                    // 设置密码
                    if (!string.IsNullOrEmpty(password))
                    {
                        zipStream.Password = password;
                    }

                    // 设置压缩级别 (0-9)
                    zipStream.SetLevel(compressionLevel);

                    foreach (string filePath in filePaths)
                    {
                        if (File.Exists(filePath))
                        {
                            CompressFile(filePath, zipStream);
                        }
                        else if (Directory.Exists(filePath))
                        {
                            CompressDirectory(filePath, zipStream, Path.GetFileName(filePath));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"压缩失败: {ex.Message}", ex);
            }
        }

        private void CompressFile(string filePath, ZipOutputStream zipStream)
        {
            FileInfo fi = new FileInfo(filePath);
            string entryName = fi.Name;

            ZipEntry newEntry = new ZipEntry(entryName);
            newEntry.DateTime = fi.LastWriteTime;
            newEntry.Size = fi.Length;

            zipStream.PutNextEntry(newEntry);

            byte[] buffer = new byte[4096];
            using (FileStream fsInput = File.OpenRead(filePath))
            {
                StreamUtils.Copy(fsInput, zipStream, buffer);
            }

            zipStream.CloseEntry();
        }

        private void CompressDirectory(string folderPath, ZipOutputStream zipStream, string baseFolderName)
        {
            string[] files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);
            
            foreach (string filePath in files)
            {
                string relativePath = filePath.Substring(folderPath.Length + 1);
                string entryName = Path.Combine(baseFolderName, relativePath).Replace("\\", "/");

                FileInfo fi = new FileInfo(filePath);
                ZipEntry newEntry = new ZipEntry(entryName);
                newEntry.DateTime = fi.LastWriteTime;
                newEntry.Size = fi.Length;

                zipStream.PutNextEntry(newEntry);

                byte[] buffer = new byte[4096];
                using (FileStream fsInput = File.OpenRead(filePath))
                {
                    StreamUtils.Copy(fsInput, zipStream, buffer);
                }

                zipStream.CloseEntry();
            }
        }

        /// <summary>
        /// 解压文件(支持密码)
        /// </summary>
        public void ExtractFilesWithPassword(string zipPath, string extractPath, string password)
        {
            try
            {
                if (!Directory.Exists(extractPath))
                {
                    Directory.CreateDirectory(extractPath);
                }

                using (FileStream fsIn = File.OpenRead(zipPath))
                using (ZipInputStream zipStream = new ZipInputStream(fsIn))
                {
                    // 设置密码
                    if (!string.IsNullOrEmpty(password))
                    {
                        zipStream.Password = password;
                    }

                    ZipEntry entry;
                    while ((entry = zipStream.GetNextEntry()) != null)
                    {
                        string outputFile = Path.Combine(extractPath, entry.Name);
                        string outputDir = Path.GetDirectoryName(outputFile);

                        if (!Directory.Exists(outputDir))
                        {
                            Directory.CreateDirectory(outputDir);
                        }

                        if (!entry.IsDirectory)
                        {
                            using (FileStream fsOut = File.Create(outputFile))
                            {
                                byte[] buffer = new byte[4096];
                                int bytesRead;
                                while ((bytesRead = zipStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    fsOut.Write(buffer, 0, bytesRead);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"解压失败: {ex.Message}", ex);
            }
        }
    }
}

参考代码 C# 将多个文件打包压缩成一个ZIP文件包 www.youwenfan.com/contentcnv/116275.html

三、功能特点

多文件打包:支持将多个文件和文件夹打包成一个ZIP文件
密码保护:支持为ZIP文件设置密码(使用 SharpZipLib)
压缩级别控制:无压缩、最快压缩、最佳压缩三种级别
进度监控:实时显示压缩进度和当前处理的文件
取消操作:支持中途取消压缩操作
文件夹压缩:支持压缩整个文件夹及其子文件夹
解压功能:支持解压ZIP文件到指定目录
文件过滤:支持按文件类型筛选要压缩的文件
覆盖控制:可选择是否覆盖已存在的输出文件


四、使用说明

4.1 基本使用

  1. 运行程序,点击"选择文件"或"选择文件夹"添加要压缩的内容
  2. 设置输出文件路径和压缩选项
  3. 点击"压缩"按钮开始压缩

4.2 高级功能

  • 密码保护:在密码框中输入密码,生成的ZIP文件将需要密码才能解压
  • 包含基目录:勾选此项将在ZIP中保留文件夹结构
  • 覆盖已有文件:勾选此项将覆盖同名的输出文件

4.3 批量操作

  • 可以同时选择多个文件和文件夹进行压缩
  • 支持拖拽文件到程序窗口(需要扩展代码)

4.4 注意事项

  • 使用 .NET 内置的 ZipFile 类不支持密码保护
  • 如果需要密码保护,请使用 SharpZipLib 版本
  • 大文件压缩可能需要较长时间,请耐心等待
posted @ 2026-06-10 09:54  bqyfa66984  阅读(8)  评论(0)    收藏  举报