如何在C#中压缩文件夹内容,即使文件正在使用中

本文关键字:文件 压缩 文件夹 | 更新日期: 2023-09-27 18:28:35

我正在学习C#,并希望使用C#winforms创建一个简单的备份程序。

我有一个程序可以压缩文件夹并将其移动到另一个位置,当文件不在使用时没有问题。如果文件正在使用,或者至少忽略正在使用的文件并继续压缩其余文件,我该怎么做呢?

我理想的解决方案是复制并压缩所有文件,即使它们正在使用中,否则我想压缩它所能压缩的所有文件,并打印它遗漏的文件列表。

这是我用来压缩并发送到另一个位置的代码

 private void btnZip_Click(object sender, EventArgs e)
    {
        string fromDirectory = txtBackupFrom.Text;
        string todaysDate = DateTime.Now.ToString("dd_MMM_yyyy");
        string toDirectory = txtBackupToLocation.Text + "/" + todaysDate + "_backup.zip";
        try
        {
            ZipFile.CreateFromDirectory(fromDirectory, toDirectory, CompressionLevel.Optimal, true);
            //Write the current date to the text file
            StreamWriter writer = new StreamWriter(runningDirectory + "''BackupDate.txt"); //open the file for writing.
            writer.Write(DateTime.Now.ToString("dd MMM yyyy")); //write the current date to the file. change this with your date or something.
            writer.Close(); //remember to close the file again.
            writer.Dispose(); //remember to dispose it from the memory.
            MessageBox.Show("Backup Successful");
        }
        catch (Exception zipException)
        {
            MessageBox.Show(zipException.Message);
        }
    }

/********编辑如下*************/

以下是我试图解决的问题。这可能不是我所学的最好的方法,但它正在中发挥作用

private void btnZip_Click(object sender, EventArgs e)
    {
        //copy location before zipping
        string copytoBeforZippingDirectory = txtBackupToLocation.Text;
        //temporary folder for zipping
        string copytotempDirectory = Path.Combine(copytoBeforZippingDirectory, "Backup_File");
        //where the files are coming from
        string copyfromDirectory = txtBackupFrom.Text;
        //today's date
        string todaysDate = DateTime.Now.ToString("dd_MMM_yyyy");
        //Where the files will end up
        string copytoDirectory = txtBackupToLocation.Text + "''" + todaysDate + "_backup.zip";
        //Create the new temporary folder for zipping
        Directory.CreateDirectory(copytotempDirectory);
        try
        {
            //Get a list of all files
            string[] fileList = Directory.GetFiles(copyfromDirectory, "*");
            // Copy all files. 
            foreach (string f in fileList)
            {
                // Remove path from the file name. 
                string fName = f.Substring(copyfromDirectory.Length + 1);
                // Use the Path.Combine method to safely append the file name to the path. 
                // Will overwrite if the destination file already exists.
                File.Copy(Path.Combine(copyfromDirectory, fName), Path.Combine(copytotempDirectory, fName), true);
            }
            MessageBox.Show("Files Copied successfully. Beginning Zipping of Files");
        }
        catch (DirectoryNotFoundException dirNotFound)
        {
            MessageBox.Show(dirNotFound.Message);
            Close();
        }
        //Zipping the temporary folder
        try
        {
            ZipFile.CreateFromDirectory(copytotempDirectory, copytoDirectory, CompressionLevel.Optimal, true);
            //Write the current date to the text file
            StreamWriter writer = new StreamWriter(runningDirectory + "''BackupDate.txt"); //open the file for writing.
            writer.Write(DateTime.Now.ToString("dd MMM yyyy")); //write the current date to the file. change this with your date or something.
            writer.Close(); //remember to close the file again.
            writer.Dispose(); //remember to dispose it from the memory.
            MessageBox.Show("Backup Successful");
        }
        catch (Exception zipException)
        {
            MessageBox.Show(zipException.Message);
        }
        //Remove the temp folder
        try
        {
            Directory.Delete(copytotempDirectory, true);
        }
        catch (Exception)
        {
            MessageBox.Show("Temporary Folder " + copytotempDirectory + " not removed");
        }
    }

如何在C#中压缩文件夹内容,即使文件正在使用中

首先,对于C#中的zip文件,没有比不使用第三个应用程序而是使用Windows中包含的powershell zipper更好的选择了。

在任何情况下,都必须将文件复制到临时副本,然后压缩临时副本

除非你想做一些真正具有破坏性的事情,否则你不能接触正在使用的文件,也不能接触其他进程使用的文件。

其他进程有可能允许"共享读取",所以您可以尝试复制/读取正在使用的文件的内容。请注意,如果其他应用程序在写入文件时不小心,它可能会给您提供不一致的数据。

打开使用"共享读取"的文件(许多示例,如是否有方法从锁定的文件中读取数据?)。您可能需要尝试其他FileAccessFileShare选项,具体取决于其他进程打开文件的方式。

 using (FileStream fileStream = new FileStream(fileName, 
        FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

ZipFile类不允许您使用这种模式打开文件,因此您需要复制(如Leandro的回答中所建议的)或使用ZipArchive.Create API手动添加文件以存档。

using (var zipToOpen = new FileStream(@"c:'users'exampleuser'release.zip", FileMode.Open))
{
  using (var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
  {
    ZipArchiveEntry readmeEntry = 
           archive.CreateEntry("Readme.txt", CompressionLevel.Optimal);
    fileStream.CopyTo(readmeEntry.Open());
  }
}

如果您只想跳过正在使用的文件,请遍历所有文件,并在尝试读取文件并跳过它们的代码周围设置try/catch。使用ZipArchive逐个构造/添加文件。