如何在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#中的zip文件,没有比不使用第三个应用程序而是使用Windows中包含的powershell zipper更好的选择了。
在任何情况下,都必须将文件复制到临时副本,然后压缩临时副本
除非你想做一些真正具有破坏性的事情,否则你不能接触正在使用的文件,也不能接触其他进程使用的文件。
其他进程有可能允许"共享读取",所以您可以尝试复制/读取正在使用的文件的内容。请注意,如果其他应用程序在写入文件时不小心,它可能会给您提供不一致的数据。
打开使用"共享读取"的文件(许多示例,如是否有方法从锁定的文件中读取数据?)。您可能需要尝试其他FileAccess
和FileShare
选项,具体取决于其他进程打开文件的方式。
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
逐个构造/添加文件。