C# 在使用System.IO.Compression提取文件期间强制替换现有文件?
我正在使用以下代码提取文件夹中的所有文件C# 在使用System.IO.Compression提取文件期间强制替换现有文件?,c#,C#,我正在使用以下代码提取文件夹中的所有文件 using (ZipArchive archive = new ZipArchive(zipStream)) { archive.ExtractToDirectory(location); } 但是,如果存在一个文件,那么它会抛出一个异常。有没有办法告诉压缩API替换现有文件 我发现一种方法是先获取所有文件名,然后检查文件是否存在并删除它。但这对我来说是非常昂贵的 看看这个:。你的
using (ZipArchive archive = new ZipArchive(zipStream))
{
archive.ExtractToDirectory(location);
}
但是,如果存在一个文件,那么它会抛出一个异常。有没有办法告诉压缩API替换现有文件
我发现一种方法是先获取所有文件名,然后检查文件是否存在并删除它。但这对我来说是非常昂贵的 看看这个:。你的问题似乎得到了解决。或者,您也可以检查。您可以将文件提取到某个临时目录,然后使用 将ovveride选项为true的“File.Copy”复制到目标目录 我知道这不是一个完美的解决方案,但这样你就不需要了
检查文件是否存在我已创建扩展名。如有任何意见,我们将不胜感激
public static class ZipArchiveExtensions
{
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
当文件夹不存在时,此代码不会引发异常,而是创建文件夹
public static class ZipArchiveExtensions
{
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
string directory = Path.GetDirectoryName(completeFileName);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
if (file.Name != "")
file.ExtractToFile(completeFileName, true);
}
}
}
从答案中重新制作一个小方法来创建所有文件夹
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
// create dirs
var dirToCreate = destinationDirectoryName;
for (var i = 0; i < file.FullName.Split('/').Length - 1; i++)
{
var s = file.FullName.Split('/')[i];
dirToCreate = Path.Combine(dirToCreate, s);
if (!Directory.Exists(dirToCreate))
Directory.CreateDirectory(dirToCreate);
}
file.ExtractToFile(completeFileName, true);
}
}
publicstaticvoidextractodirectory(此ZipArchive存档,字符串destinationDirectoryName,bool覆盖)
{
如果(!覆盖)
{
archive.extractodirectory(destinationDirectoryName);
返回;
}
foreach(存档.Entries中的ZipArchiveEntry文件)
{
字符串completeFileName=Path.Combine(destinationDirectoryName,file.FullName);
如果(file.Name==“”)
{//假定目录为空
CreateDirectory(Path.GetDirectoryName(completeFileName));
继续;
}
//创建目录
var dirToCreate=destinationDirectoryName;
对于(var i=0;i
由于我是一个十足的Linq迷,Linq ish的方式仅供参考:
using (var strm = File.OpenRead(zipPath))
using (ZipArchive a = new ZipArchive(strm))
{
a.Entries.Where(o => o.Name == string.Empty && !Directory.Exists(Path.Combine(basePath, o.FullName))).ToList().ForEach(o => Directory.CreateDirectory(Path.Combine(basePath, o.FullName)));
a.Entries.Where(o => o.Name != string.Empty).ToList().ForEach(e => e.ExtractToFile(Path.Combine(basePath, e.FullName), true));
}
当您有zip文件路径时,这非常有用
public static class ZipArchiveHelper
{
public static void ExtractToDirectory(string archiveFileName, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
ZipFile.ExtractToDirectory(archiveFileName, destinationDirectoryName);
}
else
{
using (var archive = ZipFile.OpenRead(archiveFileName))
{
foreach (var file in archive.Entries)
{
var completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
var directory = Path.GetDirectoryName(completeFileName);
if (!Directory.Exists(directory) && !string.IsNullOrEmpty(directory))
Directory.CreateDirectory(directory);
if (file.Name != "")
file.ExtractToFile(completeFileName, true);
}
}
}
}
}
嗨,我正在使用从nugget下载的DotNetZip。 我只是简单地使用这个代码。 这将自动替换目录中的文件(如果存在)。 “覆盖”
下面是一个获取zip文件路径的方法 基于公认的答案
public void ExtractZipFileToDirectory(string sourceZipFilePath, string destinationDirectoryName, bool overwrite)
{
using (var archive = ZipFile.Open(sourceZipFilePath, ZipArchiveMode.Read))
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
自.NET标准2.1以来,在以下情况下,只需将
overwriteFiles
设置为true即可:
ZipFile.ExtractToDirectory(string sourceFile、string destDir、Encoding entryNameEncoding、bool overwriteFiles)
我也有这个建议,但这对我来说是非常昂贵的。我想你没有其他选择,除了使用其他框架免费软件,正如@user960567所说的“任何对它的改进的评论都将不胜感激”,我只是添加了几行以防止抛出异常!如果(!Directory.Exists(Directory))Directory.CreateDirectory(Directory);这是一个比公认答案更可靠的解决方案。谢谢。这是否可能使用ZipFile内置类?最好用几句话解释它是如何解决问题的:)据我所知,
ExtractToDictionary
是否不接受布尔值以允许覆盖这比所有其他答案都要容易得多。@sxeros有一个重载,允许从.NET标准2.1开始使用布尔值。可能应该在回答中提到这一点。这只在.NET Core上可用,而不是在.NET Framework上,我注意到这将保留原始文件的创建时间。您可以添加File.SetCreationTimeUtc(completeFileName,File.LastWriteTime.UtcDateTime)
afterfile.ExtractToFile(completeFileName,true)代码>来修复此问题。还有一个错误,嵌套目录创建不正确。添加Directory.CreateDirectory(Path.GetDirectoryName(completeFileName))代码>修复了该问题。
public void ExtractZipFileToDirectory(string sourceZipFilePath, string destinationDirectoryName, bool overwrite)
{
using (var archive = ZipFile.Open(sourceZipFilePath, ZipArchiveMode.Read))
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}
DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;
foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));
if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}
if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
Example:
ZipFile.ExtractToDirectory("c:\\file.zip","c:\\destination_folder", Encoding.UTF8, true);